当前位置:网站首页>事务回滚异常
事务回滚异常
2022-07-05 15:26:00 【小蚂蚁hjk】
org.springframework.transaction.UnexpectedRollbackException
Spring事务传播机制汇总如下:
- PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,就加入到这个事务中。默认策略
- PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
nested 的子异常抛出 如果被catch 外部插入成功
nested 的子异常抛出 如果不被catch 外部插入失败
nested外面异常抛出 nest内部插入成功 nest也会跟着回滚
spring事务默认的传播行为:
@Transactional 等于 @Transactional(propagation=Propagation.REQUIRED)
发生异常的场景描述:
在使用Spring事务时,在一个事务A中又开了一个事务B(即存在嵌套事务),当事务B发生异常时,将异常catch后事务B会进行回滚操作,若此时异常被直接吃掉(即事务A无法得知发生过异常),则事务A会抛出如上异常。
例如:
serviceA有事务 @Transactional
serviceB有事务 @Transactional
serviceA.methodA()
{
doSomethingA();
try {
serviceB.methodB{}; //这里面有异常标记为回滚, doSetRollbackOnly(status);
}
catch {
//捕获异常转到commit时,由于已经标记为要回滚, 回滚并抛出新异常
}
doSomethingB();
}
原因:
因为methodB的传播属性设置为PROPAGATION_REQUIRED,PROPAGATION_REQUIRED的意思是,当前有事务,则使用当前事务,当前无事务则创建事务。由于methodA的传播属性也为PROPAGATION_REQUIRED,所以methodA会创建一个事务,然后methodB与methodA使用同一个事务,methodB出现异常后,将当前事务标志位回滚,由于在methodA中做了trycatch处理,程序没有终止而是继续往下走,当事务commit时,check状态,发现,需要事务回滚,所以才会出现不可预知的事务异常:因为事务被标志位回滚,所以事务回滚。
也就是说:methodA与methodB共用一个事务,methodB将事务标志为回滚,methodA中commit这个事务,然后,出现事务已经被标志回滚(methodB标志的)的异常信息。
解决方案
情况1:methodA与methodB在逻辑上不应该属于同一个事务,那么将methodB的事务传播属性修改为PROPAGATION_REQUIRES_NEW,这样,执行methodB时,会创建一个新的事务,不影响methodA中的事务。
情况2:业务A与业务B在业务逻辑上就应该属于同一个事务,那么将methodA中的try catch去掉
情况3:业务A与业务B在业务逻辑上就应该属于同一个事务,但是methodB的失败与否不能影响methodA的事务提交,那么仍然在methodA中try catch methodB,并将methodB设置为PROPAGATION_NESTED,它的意思是,methodB是一个子事务,有一个savepoint,失败时会回滚到savepoint,不影响methodA,如果成功则A、B一起提交,A与B都是一个事务,只是B是一个子事务。
情况4:业务A 有无事务无影响 去掉业务A的@Transactional
小结:
- 深入理解事务传播的各个状态含义,比如PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY、PROPAGATION_REQUIRES_NEW等
- 最初我以为是由于spring配置文件中,methodA的事务设置为ready-only=true(只读事务)的原因,经过查询资料得知,只读事务与事务传播不冲突,是两个机制。只读事务,是一个特殊的事务,该事务内,只能是查询语句,不能含有修改、更新语句,数据库可能对只读事务做优化;传播属性是母方法与子方法之间的关系表达。
- 注意,同一个类中,事务嵌套以最外层的方法为准,嵌套的事务失效;不同类中嵌套的事务才会生效;
边栏推荐
- Good article inventory
- Appium自动化测试基础 — APPium基础操作API(二)
- Ionic Cordova project modification plug-in
- Noi / 1.5 37: mercenaries
- Appium automation test foundation - appium basic operation API (II)
- I spring and autumn blasting-2
- Detailed explanation of QT creator breakpoint debugger
- lv_font_conv离线转换
- OSI seven layer model
- Reasons and solutions for redis cache penetration and cache avalanche
猜你喜欢
Why should we learn mathematical modeling?
SQL injection sqllabs (basic challenges) 11-20
Common redis data types and application scenarios
Bugku's Ping
lv_font_conv离线转换
【 note 】 résoudre l'erreur de code IDE golang
Appium automation test foundation - appium basic operation API (II)
Bugku alert
Lesson 4 knowledge summary
P1451 calculate the number of cells / 1329: [example 8.2] cells
随机推荐
Redis distributed lock principle and its implementation with PHP (2)
queryRunner. Query method
Detailed explanation of C language branch statements
16.[STM32]从原理开始带你了解DS18B20温度传感器-四位数码管显示温度
Common PHP interview questions (1) (written PHP interview questions)
通过的英特尔Evo 3.0整机认证到底有多难?忆联科技告诉你
【簡記】解决IDE golang 代碼飄紅報錯
Bugku alert
Misc Basic test method and knowledge points of CTF
数学建模之层次分析法(含MATLAB代码)
Advanced level of static and extern
Your childhood happiness was contracted by it
D-snow halo solution
Data communication foundation smart_ Link_&_ Monitor_ Link
MySQL overview
17. [stm32] use only three wires to drive LCD1602 LCD
Bugku's eyes are not real
Redis' transaction mechanism
2.3 learning content
示例项目:简单的六足步行者