spring 事务隔离级别和传播行为_Spring事务传播性与隔离性实战

一、事务传播性

1.1 什么是事务的传播性

事务的传播性一般在事务嵌套时候使用,比如在事务A里面调用了另外一个使用事务的方法,那么这俩个事务是各自作为独立的事务执行提交,还是内层的事务合并到外层的事务一块提交那,这就是事务传播性要确定的问题。下面一一介绍比较常用的事务传播性。

1.2 PROPAGATION_REQUIRED

Spring默认的事务传播机制,如果外层有事务则当前事务加入到外层事务,一块提交一块回滚,如果外层没有事务则当前开启一个新事务。这个机制可以满足大多数业务场景。

试验:

 public class BoA { public void test(){ boB.sayHello(); }}

BoA 和boB都是进行过事务增强后的bo,那么在执行test的时候会开启一个事务(或者test调用方已经存在事务则加入该事务),执行到sayHello()时候由于传播性是PROPAGATION_REQUIRED,所以sayHello方法加入到test的事务,那么sayHello和test就会同时提交,同时回滚。值得注意的是如果test里面调用sayHello时候加了trycatch没有把异常跑出去,而sayHello方法却抛出了异常,那么整个事务也会回滚,这时候调用test的外层会受到"Transaction rolled back because it has been marked as rollback-only的异常,而把sayHello真正的异常吃掉了。

平时我们都是在bo里面调用数据库操作,在rpc和screen调用bo,所以bo层不应该catch掉异常,而应该抛出来,在rpc和screen层catch异常。

1.3 PROPAGATION_REQUIRES_NEW

该传播机制是每次新开启一个事务,同时把外层的事务挂起,当前新事务执行完毕后在恢复上层事务的执行。

以上面代码为例,首先进入test方法前会开启一个事务,然后调用sayHello时候会把test的事务挂起,从新开启一个新事务执行sayHello,执行完毕后恢复test的事务。如果sayHello抛出来异常则sayHello的事务会回滚,那么test方法是否回滚那?这个要看情况,如果test在调用sayHello 时候使用了trycatch并且异常没有在catch中throw出来,那么test方法不会回滚,这时候sayHello是提交和回滚对test没有影响,。

如果test中没有加trycatch那么,test也会回滚。

1.4 PROPAGATION_SUPPORTS

该传播机制如果外层有事务则加入该事务,如果不存在也不会创建新事务,直接使用非事务方式执行。

以上面代码为例,由于PROPAGATION_SUPPORTS,所以test和sayHello都没有开启事务,没啥好讲的。

下面看下如果test隔离级别是PROPAGATION_REQUIRED,sayHello传播性是PROPAGATION_SUPPORTS的情况。这时候外层test会开启一个事务(或者test调用方已经存在事务则加入该事务),然后sayHello执行时候会加入到test的事务和1.2类似,同时提交同时回滚。

1.5 PROPAGATION_NOT_SUPPORTED

该传播机制不支持事务,如果外层存在事务则挂起外层事务 ,然后执行当前逻辑,执行完毕后,恢复外层事务。

同样这里看下如果test使用PROPAGATION_REQUIRED,sayHello传播性是PROPAGATION_NOT_SUPPORTED的情况,首先test会开启一个事务(或者test调用方已经存在事务则加入该事务),然后sayHello执行时候会挂起该事务然后在非事务内做自己的事情,做完后在恢复test的事务。 无论sayHello是否抛出异常,sayHello的事务都不会回滚,因为它不在事务范围内,那test?

这个就和1.3一样了,如果test catch住sayHello的异常没有throw出去,那么test就不回滚,否者回滚。

1.6 PROPAGATION_NEVER

该传播机制不支持事务,如果外层存在事务则直接抛出异常。

 IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'")

1.7 PROPAGATION_MANDATORY

该传播机制是说配置了该传播性的方法只能在已经存在事务的方法中被调用,如果在不存在事务的方法中被调用,会抛出异常。

 IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'");

1.8 PROPAGATION_NESTED

该传播机制特点是可以保存状态保存点,当事务回滚后会回滚到某一个保存点上,从而避免所有嵌套事务都回滚。

上面代码test和sayHello都设置为PROPAGATION_NESTED,如果sayHello抛出异常,两者还是都回滚了,因为sayHello虽然回滚到了savePoint而savepoint里面确实包含了test的操作,但是savepoint后还是会吧异常throw给test,这导致了test的回滚。

总结,只有传播性为PROPAGATION_REQUIRED||PROPAGATION_REQUIRES_NEW||PROPAGATION_NESTED时候才可能开启一个新事务。

二、事务隔离性

2.1 什么是事务的隔离性

事务的隔离性是指多个事务并发执行的时候相互之间不受到彼此的干扰,是事务acid中i,根据隔离程度对隔离性有会分类。在具体介绍事务隔离性前有必要介绍几个名词说明数据库并发操作存在的问题。

2.1.1 脏读

所谓脏读是指一个事务中访问到了另外一个事务未提交的数据,具体来说假如有两个事务A和B同时更新一个数据d=1,事务B先执行了select获取到d=1,然后更新d=2但是没有提交,这时候事务A在B没有提交的情况下执行搜索结果d=2,这就是脏读。

2.1.2 不可重复读

所谓不可重复读是指一个事务内在未提交的前提下多次搜索一个数据,搜出来的结果不一致。发生不可重复读的原因是在多次搜索期间这个数据被其他事务更新了。

2.1.3 幻读

所谓幻读是指同一个事务内多次查询(注意查询的sql不一定一样)返回的结果集的不一样(比如新增或者少了一条数据),比如同一个事务A内第一次查询时候有n条记录,但是第二次同等条件下查询却又n+1条记录,这就好像产生了幻觉,为啥两次结果不一样那。其实和不可重复读一样,发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据。不同在于不可重复读是数据内容被修改了,幻读是数据变多了或者少了。

2.2、事务隔离级别

为了解决事务并发带来的问题,才有了sql规范中的四个事务隔离级别,不同隔离级别对上面三个问题部分或者全部做了避免。注意:下面试验用的两个终端都是同时执行了begin为了模拟事务并发。

2.2.1 Read Uncommitted

读未提交隔离级别,就是指一个事务中可以读取其他事务未提交的数据,这个级别会导致脏读。

本文都是以mysql为例引擎InnoDB,mysql默认事务隔离级别为Repeatable_Read:如图:

99b0890d7ad44a4c5e47659244e0fdc1.png

下面我们更改隔离级别为Read Uncommitted :

33f69310dde25f66a56239f175a19c6c.png

试验:

下面我们打开两个mysql终端,并且关闭自动提交.

终端一:

dddeb92f35f554a8d9a7b6c776a11903.png

终端二:

5cecd015b506e6f1c164f987c910e6b1.png

终端一我们开启了一个事务,并且插入了一条数据但是没有提交事务,但是终端二却查询出来了。

终端一执行rollback:

f3e95f1686ca2686ee6f48dac01522a7.png

终端二搜索:

157ff3f026eee806d074eb7592146566.png

在终端1回滚后,终端二有搜不到了,所以有可能在终端一没有回滚时候终端二已经获取并使用终端一的数据,而终端一回滚后,数据已经被使用过了,所以导致了脏读。

总结:该隔离级别会导致 脏读,不可重复读,幻读,是最低级的隔离级别,一般不用的。

2.2.2 Read Committed

读已提交隔离级别,一个事务只能读取到其他事务已经提交的数据,可能导致同一个事务中多次搜查结果不一样。

试验:修改事务隔离级别为Read Committed,

c0540bb64ff3723c7f5ef9c0e550189a.png

终端一:

43d3d4e1fa37aebc473e91457d5d42d1.png

终端二:

64efb9a6807a97b7aa3a4c280144cf00.png

由于终端一执行后没有commit,所以终端二查询不到。

下面终端一执行commit:

19e0783af314ff56276c1d91a6bc3302.png

终端二再次执行查询:

2f588b4cdd4f0bdb23f1f9158463cb88.png

终端一提交后,终端二就可以搜查出来了。

总结:该隔离级别会导致不可重复读和幻读,避免了脏读,oracle默认是该隔离级别。实际项目使用mybaits时候虽然隔离级别是read committed,但是在一个事务中多次搜索还是会是同一个结果,这是因为mybatis一级缓存的原因

2.2.3 Repeatable Read

可重复读隔离级别,一个事务内多次查询数据时候查询的数据内容和第一次查询的一致也就是说第一次查询出来的数据没有被修改,而不管其他事务有没有对这些数据新修改。但是可能其他事务新增一条数据,导致一个事务内查询的结果集里面多了一条记录。mysql默认隔离级别就是这个。

试验:

首先修改事务隔离级别为可重复读:

d3967cb8ae07f3c382de3b8a1b385a80.png

模拟修改数据情况:

终端一:

0ab249db52411963102a40e32c2c3505.png

终端二:

6d5b9a1aae9478aba9f530a5795e93f7.png

可以知道终端一已经提交的数据在终端二的事务中还是查不到(注意终端二执行begin要在终端一执行commit前,因为我们要模拟并发事务)。

下面在模拟下新增数据情况

终端一:

e195eee7128e3adca7b8b5c04f13d8ef.png

终端二:

a48866bf67913630111872ec989f39bd.png

终端一插入了一条记录并且提交,但是终端二还是查询不到新增的记录

总结:这里有点奇怪,按照其他资料显示该隔离级别应该是避免了 脏读,不可重复读,但是还存在幻读,但是试验表明不存在幻读

2.2.4 Serializable

串行化隔离级别,就是多个事务串行化一个个按照顺序执行,这种不存在并发情况,所以可以避免所有事务并发问题。

终端一:

d1f6d29fa569be43b1fb7cc98dbe377b.png

终端二:

d1c14ed50bbd0ef85958792e11b76e90.png

可以看到终端一打开一个事务后,事务二的insert语句会等待知道事务一提交或者超时。

超时:

7704144efae98797536dece6d0821beb.png

链接:https://www.jianshu.com/p/249f2cd42692

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370143.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端为什么非要动静分离 说一下CDN托管的意义

大型Web应用对速度的追求并没有止步于仅仅利用浏览器缓存,因为浏览器缓存始终只是为了提升二次访问的速度,对于首次访问的加速,我们需要从网络层面进行优化,最常见的手段就是CDN(Content Delivery Network,…

unity语音聊天之 www.GetAudioClip

最近在开发语音聊天功能,游戏需要跨平台安卓与ios,上传本地录制的wav文件至服务器后,需要根据服务器返回的地址进行语音文件的下载并进行播放。 这里通过使用www进行下载并播放 其中在ios播放时却不行了,查询官方文档后发现,ios必…

轻谈BFC

BFC 定义 CSS2.1的定义 Block formatting contexts 9.4.1 Block formatting contexts Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with overflow other …

Java中的Selenium / WebDriver示例

几年前,我正在忙于一些工作,客户希望了解如何解决现实世界中的问题。 他们要求我自动化woot.com网站上的某些任务。 他们的任务是访问各个网站,并阅读当天商品的名称和价格。 我写了一些Selenium代码,以为可以将其张贴在这里&am…

c语言中怎样实现空格的替换,C语言实现去除字符串中空格的简单实例

在网上看了些去除空格的代码,觉得都不是很简洁,就自己写代码实现它本着高效率,不使用额外存储空间的想法实现该功能去除空格一共有三种:1、去除全部空格;2、一种是去除左边空格;3、去除右边空格想去除左右两边空格,只要先去除左边…

python消息队列中间件_python-RabbtiMQ消息队列

1.RabbitMQ简介AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在&#xff…

CSS position(定位)属性

关于CSS position,来自MDN的描述: CSS position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left 属性则决定了该元素的最终位置。 然后来看看什么是文档流(normal flow),下面是 www.w3.org 的描述: Normal flo…

tomcat配置文件server.xml详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[] 元素名 属性 解释 server port 指定一个端口,这个端口负责监听关闭tomcat 的请求 shutdown 指定向端口发送的命令字符串 service name 指定service 的名字 Con…

均值,方差,协方差,协方差矩阵,特征值,特征向量

大牛博客,收藏一下 http://blog.csdn.net/yangleo1987/article/details/52845912转载于:https://www.cnblogs.com/gaohai/p/8086626.html

Java ByteBuffer –速成课程

以我的经验,当开发人员第一次遇到java.nio.ByteBuffer时,会引起混乱和细微的错误,因为如何正确使用它尚不明显。 在我对API文档感到满意之前,需要反复阅读API文档和一些经验以实现一些微妙之处。 这篇文章是关于如何正确使用它们的…

c语言cth三角函数表示,三角函数与双曲函数基本公式对照表

圆函数(三角函数)1.基本性质:sin tan cos x x x ,cos cot sin xx x 1sec cos x x ,1csc sin x x tan cot 1x x sin csc 1x x sec cos 1x x 22sin cos 1x x 221tan sec x x ,221cot csc x x 2.奇偶性:sin()sin x x -- cos()cos x x - tan()tan x x --3.…

实现编辑功能有哪几个action_Web 应用的撤销重做实现

背景前不久,我参与开发了团队中的一个 web 应用,其中的一个页面操作如下图所示:GIF这个制作间页面有着类似 PPT 的交互:从左侧的工具栏中选择元素放入中间的画布、在画布中可以删除、操作(拖动、缩放、旋转等&#xff…

为什么我们要做三份 Webpack 配置文件

时至今日,Webpack 已经成为前端工程必备的基础工具之一,不仅被广泛用于前端工程发布前的打包,还在开发中担当本地前端资源服务器(assets server)、模块热更新(hot module replacement)、API Pro…

使用maven插件构建docker镜像

为什么要用插件 主要还是自动化的考虑,如果额外使用Dockerfile进行镜像生成,可能会需要自己手动指定jar/war位置,并且打包和生成镜像间不同步,带来很多琐碎的工作。 插件选择 使用比较多的是spotify的插件:https://github.com/spo…

windows下如何安装pip以及如何查看pip是否已经安装成功?

最近刚学习python,发现很多关于安装以及查看pip是否安装成的例子都比较老,不太适合于现在(python 3.6 )因此,下一个入门级别的教程。 0:首先如何安装python我就不做介绍了。 1:如果安装的是pyth…

检查用户显示器的分辨率

检查用户显示器的分辨率 转载于:https://www.cnblogs.com/Renyi-Fan/p/8088012.html

android 字体 dpi,详解Android开发中常用的 DPI / DP / SP

Android的碎片化已经被喷了好多年,随着国内手机厂商的崛起,碎片化也越来越严重,根据OpenSignal的最新调查,2014年市面上有18796种不同的Android设备,作为开发者,一个无法回避的难题就是需要适配各种各样奇奇…

android studio闪退代码不报错_代码不报错,不代表真的没错

今天是生信星球陪你的第695天大神一句话,菜鸟跑半年。我不是大神,但我可以缩短你走弯路的半年~就像歌儿唱的那样,如果你不知道该往哪儿走,就留在这学点生信好不好~这里有豆豆和花花的学习历程,从新手到进阶&#xff0c…

Centos7操作系统部署指南

一、硬件环境: Dell R620 二、软件环境: Centos6.4 X86_64 KVM Windows7vnc 三、安装说明 操作系统更新之迅速,让作为新手的系统运维人员有点措手不及,相对于老手就胸有成竹。怎么讲?由于老手对技术方向把握的非常好&…

Eclipse插件中的SLF4J登录

一直都在使用Maven和纯Java库进行开发,我从没想过在开发Eclipse插件时发出一些日志语句可能会成为问题。 但是,在Eclipse开发人员的想象中,一切似乎总是在Eclipse环境中,而Eclipse宇宙之外则什么都没有。 如果您使用Google搜索上…