事务失效的场景
在MYSQL场景下
create、alter等DDL SQL语句是不支持回滚的,Mysql8会隐式提交DDL语句的事务(隐式提交可以简单理解成Mysql自动提交)。
在工作中,mysql的insert、update、delete这类语句被称为DML(Data Manipulation Language)数据操作语言,create、alter、drop这类语句被称为DDL(Data Definition Language)数据定义语言。Mysql对于DDL操作是隐式提交的,如果DML和DDL语言混合,DDL语言隐式提交则会把DML的数据一同提交,因此为了能正常回滚DML的数据,正确的做法应该把DML和DDL分成多个事务进行处理,特别是DDL要独立放到一个事务或无事务中去执行
优化思路
- 创建物理表和物理字段(既DDL操作)通过事务二操作
- 保存基本、JSON等信息(既DML操作)通过事务一操作,同时事务一还需要负责启动事务二
- 如果事务二执行有错误,则需要抛错给事务一,让事务一回滚
在一个事务中启动另一个事务方法
在一个事务中启动另一个事务方法
Spring的事务传播行为(spring在方法中的调用只会用最开始的事务来处理1.)
事务传播行为:方法调用链中嵌套事务方法之间的事务如何传播和交互的规则
Spring提供了7种规则:
- REQUIRED:表示支持当前事务,如果当前没有事务,就新建一个事务【默认】
- REQUIRES_NEW:表示支持当前事务,但是如果当前有事务,就将当前事务挂起,新建一个事务
- SUPPORTS:表示支持当前事务,如果当前没有事务,就非事务的方式执行
- NOT_SUPPORTED:表示不支持当前事务,如果当前有事务,就将当前事务挂起
- MANDATORY:表示必须支持当前事务,如果当前没有事务,就抛出异常
- NEVER:表示不支持当前事务,如果当前有事务,就抛出异常
- NESTED:表示开启一个新的嵌套事务,如果当前没有事务,就新建一个事务,如果当前有事务,就在当前事务中创建一个嵌套的事务
在SpringBoot场景下
常见场景:异常捕获处理,抛出检查异常,非public方法
异常捕获处理导致事务失效的原因
事务通知只有捉到了目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉了异常,事务无法知悉。
解决方案
在catch块添加throw new RuntimeException(e)抛出
抛出检查异常导致事务失效的原因
Spring默认只会回滚非检查异常(unchecked exceptions(昂柴克的spring默认配置),通常是继承自RuntimeException的异常)所以当抛出RuntimeException时事务才会回滚)
解决方案
配置rollbackFor属性
非public方法导致事务失效的原因
Spring为方法创建代理、添加事务通知、前提条件都是该方法是public的
解决方案
改为public

Comments 2 条评论
写的挺不错的
牛逼