事务失效的场景

xiaojiuaigc@163.com 发布于 2024-10-25 327 次阅读


事务失效的场景

 

在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