Spring 七种事务传播性介绍
作者:vivo 互联网服务器团队 - Zhou Shaobin
本文主要介绍了Spring事务传播性的相关知识。
Spring中定义了7种事务传播性:
PROPAGATION_REQUIRED
PROPAGATION_SUPPORTS
PROPAGATION_MANDATORY
PROPAGATION_REQUIRES_NEW
PROPAGATION_NOT_SUPPORTED
PROPAGATION_NEVER
PROPAGATION_NESTED
在Spring环境中,含有事务的方法嵌套调用,事务是如何传递的规则,以及每种规则是如何开展工作的。文章还提到每种事务传播性是如何使用的,方便读者依据实际的场景,使用不同的事务规则。
一、什么是Spring事务的传播性
Spring 事务传播性是指, 在Spring的环境中,当多个含有事务的方法嵌套调用时,每个事务方法都处于自己事务的上下文中,其提交或者回滚行为应该如何处理。
通俗讲,就是当一个事务方法调用另外一个事务方法时,事务如何跨上下文传播。
1)当事务方法A调用事务方法B时,事务方法B是合并到事务方法A中,还是开启新事务?
2)当事务方法B抛出异常时 ,在合并事务或者开启新的事务的场景中,事务的回滚是如何处理的 ?
以上事务的处理规则,都取决于事务传播级别的设置。
二、事务的传播性都有哪些行为
事务的传播行为,主要分为三种类型,分别是:支持当前事务、不支持当前事务、嵌套事务。
2.1 支持当前事务
REQUIRED:默认的事务传播级别,表示如果当前方法已在事务内,该方法就在当前事务中执行,否则,开启一个新的事务并在其上下文中执行。
SUPPORTED:当前方法在事务内,则在其上下文中执行该方法,否则,开启一个新的事务。
MANDATORY:必须在事务中执行,否则,将抛出异常。
2.2 不支持当前事务
REQUIRES_NEW:无论当前是否有事务上下文,都会开启一个事务 。如果已经有一个事务在执行 ,则正在执行的事务将被挂起 ,新开启的事务会被执行。
事务之间相互独立,互不干扰。
NOT_SUPPORTED:不支持事务,如果当前存在事务上下文,则挂起当前事务,然后以非事务的方式执行。
NEVER:不能在事务中执行,如果当前存在事务上下文,则抛出异常。
2.3 嵌套事务
NESTED:嵌套事务,如果当前已存在一个事务的上下文中,则在嵌套事务中执行,如果抛异常,则回滚嵌套事务,而不影响其他事务的操作。
三、每种事务的传播性如何工作
3.1 REQUIRED
默认的事务传播行为,保证多个嵌套的事务方法在同一个事务内执行,并且同时提交,或者出现异常时,同时回滚。
这个机制可以满足大多数业务场景。
例子 :
1)类TestAService的方法通过声明式事务的方式,加上了事务注解@Transactional ,并设置事务的传播性为REQUIRED。
2)调用者调用TestAService的A方法时,如果调用者没有开启事务,那么A方法会开启一个事务。
A方法的具体执行过程如下 :
a. 执行insert,但没有提交;
b. 调用TestBServcie的B方法,由于B方法也声明了事务,并且传播性是REQUIRED,所以方法B的事务,合并到方法A开启的事务中。
c. 方法B执行insert操作,此时也没有提交。
3)由于这两个方法的操作都在同一个事务中执行,当这两个方法所有操作执行成功之后,提交事务。
嵌套调用链路:
当方法B 执行时抛出了 Exception 异常后,事务是如何处理的 ?
1)方法B声明了事务,insert操作会回滚
2)由于方法A和方法B 同属一个事务,方法A也会执行回滚,由此说明该规则保证了事务的原子性。
嵌套调用,异常后的链路:
如果 方法B 抛出异常后,方法A 使用 try-catch 处理了方法B的异常(如下代码),并没有向外抛出,此时事务又如何处理的 ?
方法A也会回滚。
从事务的特性我们可知,事务具有原子性。方法A和方法B同属一个事务,当方法B抛出异常,触发回滚操作后,整个事务的操作都会回滚。
因此,Spring 在处理事务过程中,当事务的传播性设置为REQUIRED,在整个事务的调用链上,任何一个环节抛出的异常都会导致全局回滚。
3.2 REQUIRES_ NEW
每次都开启一 个新的事务。
例子:
上面例子中,方法B的传播性设置为 REQUIRES_NEW,方法A仍然是REQUIRED,当A调用B时,具体调用链路如下:
具体执行过程:
方法A被执行前,如果调用者没有开启事务,方法A开启一个事务1,然后执行insert ,此时没有提交;
方法B的事务传播性设置为REQUIRES_NEW,当被方法A调用时,此时方法A的事务1会被挂起,方法B开启自己的事务2,然后执行insert,此时并没有提交;
当方法B执行完毕后,提交事务2;
恢复事务1,最终提交。
当 方法B 执行时抛出了异常,会发生什么?
方法B的insert操作会被回滚掉,方法A不受影响。但这里有个前提,方法A需要try-catch方法B的异常,使其异常不会往上传递,从而导致方法A接收到异常,导致回滚。
3.3 SUPPORTED
当外层方法A存在事务,方法B加入到当前事务中,以事务的方式执行。
当外层方法A不存在事务,方法B不会创建新的事务,以非事务的方式执行。
例子1:
以上例子,方法A没有加事务注解,方法B的加了事务注解,并且传播为SUPPORTS。
具体执行过程:
方法A以非事务的方式执行insert操作。
方法B被调用,由于其外层事务A没有开启事务,方法B也是以非事务方法执行insert操作。
例子2:
以上例子,方法A和B都加上了事务注解,其中方法A的传播性为REQUIRED,方法B的传播性为SUPPORTS。
具体执行过程:
如果方法A的调用方没有开启事务,则方法A开启事务,并执行insert操作,但没有提交;
方法B被调用,由于其外层方法A开启了事务,因此方法B加入到方法A开启的事务中,并执行insert,但没有提交;
当事务中的所有操作执行成功后,事务提交。
3.4 NOT_SUPPORTED
不支持事务。
如果外层方法存在事务,则挂起外层事务,以非事务方式执行,执行完毕后,恢复外层事务。
例子:
以上例子:方法A和B都加上了事务注解,方法A的传播性为REQUIRED,方法B为NOT_SUPPORTED。
具体执行过程:
如A的调用方没有开启事务,方法A开启事务,并执行insert,但没有提交。
方法A调用方法B时,方法B的传播性为NOT_SUPPORTED,不支持事务,然后挂起外层方法A的事务,方法B以非事务的方式执行insert。
方法B执行完毕后,恢复方法A的事务,最终提交事务。
调用链路过程:
3.5 NEVER
不支持事务
当外层方法A开启了事务,方法B抛出异常
例子:
以上代码,两个方法都打上了事务注解,方法A的传播性是REQUIRED,方法B的传播性是NEVER。
具体执行过程:
方法A开启事务,执行insert,没有提交。
含有事务的方法A调用方法B,方法B的传播性是NEVER,表示不支持事务,因此方法B抛出异常。
方法A的事务执行回滚。
3.6 MANDATORY
必须在事务中执行。
如果外层方法A没有开启事务,方法B抛出异常。
如果外层方法A开启了事务,方法B加入事务,方法A&B在同一事务中执行。
例子:
以上例子,方法A没有加事务注解,方法B 的传播性为 MANDATORY。
具体执行过程:
方法A的调用方如果本身没有开启事务,方法A执行前不会开启事务。
当非事务方法A调用方法B时,由于方法B的传播性为MANDATORY,必须在事务中执行,条件不满足,抛出异常。
3.7 NESTED
嵌套事务
如果外层方法A不存在事务,内层方法B的规则与REQUIRED 一致。
如果外层方法A存在事务,内层方法B做为外层方法A事务的子事务执行,两个方法是一起提交,但子事务是独立回滚。
内层方法B抛出异常,则会回滚方法B的所有操作,但不影响外层事务方法A。(方法A需要try-catch子事务,避免异常传递到父层事务)
外层方法A回滚,则内层方法B也会回滚。
该传播性的特点是可以保存状态点,当回滚时,只会回滚到某一个状态点,保证了子事务之间的独立性,避免嵌套事务的全局回滚。
例子:
以上例子,方法A的传播性为REQUIRED,方法B为NESTED。
具体执行过程:
方法A执行时,如调用方没有开启事务,则开启一个事务。
方法B被外层方法A调用时,因为方法B的传播性为NESTED,方法B在此处建立savepoint,标记insert行为。
当方法B抛出异常,其insert操作会回滚,但只会回滚到savepoint,(前提是方法A要try-catch方法B,使方法B的异常不会往外传递)。
方法B回滚后,方法A的事务提交。
调用链路:
四、总结
本文解释了Spring框架中的事务传播性,即多个业务方法之间调用时事务如何处理的规则。Spring提供了七种传播级别,如PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW等。
每种级别都有适用场景和限制,本文提供了一些示例,介绍了声明式事务如何使用,每种事务的规则,产生哪种行为,当方法抛出异常时,事务的提交和回滚是如何被处理的。正确处理事务对于任何企业级应用程序都是必要的,了解Spring事务传播性是构建高效、可靠和可扩展应用程序的关键。
Spring 七种事务传播性介绍的更多相关文章
- 手把手带你实战下Spring的七种事务传播行为
目录 本文目录 一.什么是事务传播行为? 二.事务的7种传播行为 三.7种传播行为实战 本文介绍Spring的七种事务传播行为并通过代码演示下. 本文目录 一.什么是事务传播行为? 事务传播行为(pr ...
- spring事务:事务控制方式,使用AOP控制事务,七种事务传播行为,声明事务,模板对象,模板对象原理分析
知识点梳理 课堂讲义 1)事务回顾 1.1)什么是事务-视频01 事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败. 1.2)事务的作用 事务特征(ACID) 原子 ...
- Spring 7种事务传播类型
转载:https://www.cnblogs.com/originate918/p/6226342.html PROPAGATION_REQUIRED及其他6种事务传播行为种类. Spring在Tra ...
- Spring的七种事务传播机制
概述 当我们调用一个基于Spring的Service接口方法(如UserService#addUser())时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其它的Se ...
- Spring 7种事务传播行为
1.PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置. 2.PROPAGATION_SUPPORTS:支持当前事务,如 ...
- spring 事务传播性
一.什么是事务传播性 大白话讲就是,方法之间互相调用的时候,事务如何传播,比如A()调用B(),B()的事务是和A()共用一个事务(失败一起提交)? 还是新事务(两者事务互不影响)?,还是说B()不需 ...
- 面试官:说说Spring中的事务传播行为
前言 在开发中,相信大家都使用过Spring的事务管理功能.那么,你是否有了解过,Spring的事务传播行为呢? Spring中,有7种类型的事务传播行为.事务传播行为是Spring框架提供的一种事务 ...
- Spring五个事务隔离级别和七个事务传播行为
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt216 Spring五个事务隔离级别和七个事务传播行为 1. 脏读 :脏读就是 ...
- Spring事务——传播性
传播性 事务传播行为是为了解决业务层方法之间互相调用的事务问题,当一个事务方法被另一个事务方法调用时,事务该以何种状态存在?例如新方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运 ...
- spring事物的七种事物传播属性行为及五种隔离级别
首先,说说什么事务(Transaction). 事务,就是一组操作数据库的动作集合.事务是现代数据库理论中的核心概念之一.如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务.当 ...
随机推荐
- Kruskal重构树 学习笔记
Kruskal 重构树 最大生成树将部分内容倒置即可 回顾:Kruskal 基本信息 求解最小生成树 时间复杂度:\(O(m \log m)\) 更适合稀疏图 算法思想 按照边权从小到大排序 依次枚举 ...
- Springboot中使用线程池的三种方式
前言 多线程是每个程序员的噩梦,用得好可以提升效率很爽,用得不好就是埋汰的火葬场. 这里不深入介绍,主要是讲解一些标准用法,熟读唐诗三百首,不会作诗也会吟. 这里就介绍一下springboot中的多线 ...
- jenkins更换国内插件源
sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' ...
- MOOC慕课课表
8. 教育法学,共11单元---课件全开放状态,可以1次全学完开课时间: 2020年08月17日 ~ 2020年12月16日进行至第1周,共18周学时安排: 3-5小时每周 9. 教师职业道德与教育政 ...
- MySQL低配数据库被大量数据导入时KO
在一个低配MySQL数据库(笔记本电脑虚机环境,虚机配置2CPU/3G内存),在3000万级别的大量数据LOAD DATA方式导入时,坚持一小时后,终于被KO了,甚至没写下任何有用的日志,只是在操作界 ...
- 深入MySQL索引,这篇千万不能错过
大家好,我是[码老思],索引是一个数据库绕不开的话题,今天和大家一起聊聊. 1. 索引 索引是对数据库表中一列或多列的值进行排序的一种结构. MySQL索引的建立对于MySQL的高效运行是很重要的,索 ...
- Opencv系列之一:简介与基本使用
1 Opencv简介 Opencv是计算机视觉中经典的专用库,其支持多语言,跨平台,功能强大.Opencv-Python为Opencv提供了Python接口,使得使用者在Python中能够调用C/C+ ...
- 创建vue项目并搭建JSONSERVER
1.该前提是你已经搭建好vue-cli脚手架,开始创建一个新项目,输入 vue init webpack demo(demo是自定义项目名). 2.cd demo 进入项目安装依赖 3.在已经创建的项 ...
- Qt OpenGL textures详解
1. 初始化opengl资源 Q_INIT_RESOURCE:textures(资源名称) QSurfaceFormat:定义3d面显示方式 如果在vs+qt vs tools 中无法正常显示3d图形 ...
- 浅析KV存储之长尾时延解决办法
本文分享自华为云社区<浅析KV存储之长尾时延问题,华为云 GeminiDB Redis 探寻行业更优解决方案!>,作者:华为云数据库GaussDB NoSQL团队. 目前,KV存储的广泛使 ...