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,…

CSS position(定位)属性

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

Java ByteBuffer –速成课程

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

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

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

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搜索上…

Java EE 7社区调查结果!

在JSR 342下可以继续进行Java EE 7的工作。一切进展顺利,Java EE 7现在处于“初稿审查”阶段。 在11月初, Oracle发布了一个有关即将推出的Java EE 7功能的小型社区调查 。 昨天结果公布了。 超过1,100名开发人员参加了调查,并且几乎对每个问…

CSS(三)

CSS盒子模型 盒子模型解释 元素在页面中显示成一个方块,类似一个盒子,CSS盒子模型就是使用现实中盒子来做比喻,帮助我们设置元素对应的样式。盒子模型示意图如下: 把元素叫做盒子,设置对应的样式分别为:盒…

南昌互联网行业协会筹办者祝真和华罡团队-2014年12月江西IDC排行榜

他出自军营,拥有一身正气。 他在南昌创业,立意卓越。 从站点開始、到微营销、到线上教育,全面开花。 他在朋友圈看到不对的内容,就会即时批评。 他对朋友,又是很的和蔼可亲。 他就是南昌华罡网…

我应该使用32位还是64位JVM?

这是我在企业软件开发生涯中多次遇到的问题。 我不得不每隔一段时间就提供有关配置特定新环境的建议。 而且,很多时候,手头的问题与“我应该使用32位或64位JVM”有关。 老实说,一开始我只是掷硬币。 而不是给出合理的答案。 (对不…

android studio点击图片,如何在Android Studio中的模拟器图库中添加图像?

如何在Android Studio中的模拟器图库中添加图像?我正在开发图像过滤器应用程序。 但是,如果我没有任何图像,就无法真正尝试。我知道我可以在电话中对其进行测试,但这并不相同,因为我需要错误消息和其他内容。我只想从A…

android移动应用基础教程源代码,Android移动应用基础教程 【程序活动单元Activity】...

本章目录一、Activity的生命周期1、生命周期状态2 、生命周期方法3、横竖屏切换时的生命周期二、Activity的创建配置和关闭1、Activity的创建2、配置Activity3、开启和关闭Activity三、Intent与IntentFilter1、Intent介绍1.1 意图的概念1.2 显式意图1.3 隐式意图2、IntentFilte…

Python中使用subplot在一张画布上显示多张图

subplot(arg1, arg2, arg3) arg1: 在垂直方向同时画几张图arg2: 在水平方向同时画几张图arg3: 当前命令修改的是第几张图 t np.arange(0,5,0.1) y1 np.sin(2*np.pi*t) y2 np.sin(2*np.pi*t) plt.subplot(211) plt.plot(t,y1,b-.) plt.subplot(212) plt.plot(t,y2,r--) plt.s…

Java 8:从PermGen到元空间

您可能已经知道,现在可以下载JDK 8 Early Access 。 这使Java开发人员可以尝试Java 8的一些新语言和运行时功能。这些功能之一是完全删除自Oracle自JDK 7发行以来就宣布的Permanent Generation(PermGen)空间。例如,自JDK 7起&…

浏览器缓存问题原理以及解决方案

浏览器缓存问题: 简单来说,浏览器缓存就是把一个已经请求过的Web资源(如html页面,图片,js,数据等)拷贝一份副本储存在浏览器中。缓存会根据进来的请求保存输出内容的副本。当下一个请求来到的时…

Scikit-Learn机器学习入门

现在最常用的数据分析的编程语言为R和Python。每种语言都有自己的特点,Python因为Scikit-Learn库赢得了优势。Scikit-Learn有完整的文档,并实现很多机器学习算法,而每种算法使用的接口几乎相同,可以非常快的测试其它学习算法。 Pa…