当前位置: 首页 > article >正文

Transaction rolled back because it has been marked as rollback-only问题解决

transaction rolled back because it has been marked as rollback-only
简略总结=>
发生场景:try-catch多业务场景
发生原因:业务嵌套,事务管理混乱,外层业务与内层业务抛出异常节点与回滚节点不一致。
解决方式:修改业务的事务嵌套关系为[ NESTED ],保证内层业务的异常不会设置外层的回滚

Spring中的事务拥有多种隔离机制,类似默认的REQUIRED,REQUIRES_NEW。
这个问题会发生的原因则是事务的隔离机制问题。
业务A是外层业务,调用了业务B内层业务。并且try-catch了它
类似

public void testA(){
    try{
    	testB();   
    }catch(){
    }
}

如果这是一个有事务的场景,那么如果testB()方法抛出异常,而异常被testA()的
try-catch捕获了,那么spring在执行testA()的事务commit时就会抛出
transaction rolled back because it has been marked as rollback-only的异常。
因为内层业务在发生异常的时候,标注了改事务是需要回滚的,但是外层捕获了异常后继续执行,方法完成以后提交便出错了,无法提交需要被回滚的内容。

解决方法则是修改testA()与testB()之间的事务隔离,将本来继承或者加入testA()事务的testB()的事务隔离级别设置为 NESTED;

@Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class)

nested的意思是嵌套事务,如果外层有事务那么嵌套一个事务在其中,如果不存在事务则新建一个事务。参考地址:NESTED
如果使用了这个级别,那么testB()会嵌套在testA()里,遇到异常时会回滚到开始执行testB()的数据,将原来的整体事务回滚修改为局部事务回滚,这样的话在testA()捕获了异常以后也不会影响testA()的其他业务执行。

另话:
除了NESTED外还有REQUIRES_NEW这个级别,它是新建一个新的事务,和NESTED的区别就是,REQUIRES_NEW是两个事务,同级,A跟B各自创建了一个事务,NESTED是父子级,B的事务在A里面。为什么这里选用了NESTED的级别没用REQUIRES_NEW呢,是因为我在做业务的时候发现使用REQUIRES_NEW包住的代码无法写入数据库,因为外层testA()的事务没有结束,数据库的表被testA()锁住了,导致无法写入,NESTED则没有这种问题。


http://www.kler.cn/a/597362.html

相关文章:

  • Ceph集群2025(Squid版)快速对接K8S cephFS文件存储
  • Web测试
  •  UNIX网络编程笔记:TCP客户/服务器程序示例
  • Redis GEO 命令详解:轻松实现“附近的人“功能
  • [特殊字符]1.2.1 新型基础设施建设
  • nginx5天时间从0到熟练掌握学习计划
  • [特殊字符] Blender + 在线渲染农场加速渲染|渲染 101 极简指南
  • Centos操作系统安装及优化
  • 【ES】深度分页
  • JVM的组成--运行时数据区
  • Git入门到精通
  • 鸿蒙 元服务摘要
  • pip install jupyter 报错
  • 【嵌入式狂刷100题】- 1基础知识部分
  • Go语言的基础类型
  • Linux上位机开发实战(camera视频读取)
  • 大语言模型的“细胞“:拆解语言模型的DNA——Token
  • STM32G070CBT6采用定时器实现1秒内发送N次数据
  • 【leetcode hot 100 22】括号生成
  • 使用Pycharm一键将.ui文件生成.py文件配置教程