REQUIRED、REQUIRES_NEW、NESTED 到底有什么区别?外层回滚了里层还在吗?里层抛异常被外层吞掉会怎样?外面没有事务时每种传播行为是什么表现?这篇用 7 种传播行为乘 4 种场景,在 Spring Framework 7.0.9 和 MySQL 26.7.0 上逐个跑出来。
REQUIRED 外有事务、都成功 → 提交后的行 outer+inner inner 事务活跃=true,inner 连接 12(outer 连接 12) REQUIRES_NEW 外有事务、都成功 → 提交后的行 outer+inner inner 事务活跃=true,inner 连接 13(outer 连接 12) NESTED 外有事务、都成功 → 提交后的行 outer+inner inner 事务活跃=true,inner 连接 12(outer 连接 12) SUPPORTS 外有事务、都成功 → 提交后的行 outer+inner inner 事务活跃=true,inner 连接 12(outer 连接 12) NOT_SUPPORTED 外有事务、都成功 → 提交后的行 outer+inner inner 事务活跃=false,inner 连接 13(outer 连接 12) MANDATORY 外有事务、都成功 → 提交后的行 outer+inner inner 事务活跃=true,inner 连接 12(outer 连接 12) NEVER 外有事务、都成功 → 提交后的行 ✗ IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
四种加入同一个连接,REQUIRES_NEW 与 NOT_SUPPORTED 用另一个连接,NEVER 抛异常。
REQUIRED 外有事务、inner 成功后 outer 抛异常 → 剩下的行 (空) REQUIRES_NEW 外有事务、inner 成功后 outer 抛异常 → 剩下的行 inner NESTED 外有事务、inner 成功后 outer 抛异常 → 剩下的行 (空) SUPPORTS 外有事务、inner 成功后 outer 抛异常 → 剩下的行 (空) NOT_SUPPORTED 外有事务、inner 成功后 outer 抛异常 → 剩下的行 inner MANDATORY 外有事务、inner 成功后 outer 抛异常 → 剩下的行 (空) NEVER 外有事务、inner 成功后 outer 抛异常 → 剩下的行 ✗ IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
加入外层事务的跟着回滚,独立事务或无事务的内层行留下。
REQUIRED 外有事务、inner 抛异常被 outer 捕获 → outer 结束时 UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only;行 (空) REQUIRES_NEW 外有事务、inner 抛异常被 outer 捕获 → outer 正常结束,行 outer NESTED 外有事务、inner 抛异常被 outer 捕获 → outer 正常结束,行 outer SUPPORTS 外有事务、inner 抛异常被 outer 捕获 → outer 结束时 UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only;行 (空) NOT_SUPPORTED 外有事务、inner 抛异常被 outer 捕获 → outer 正常结束,行 outer+inner MANDATORY 外有事务、inner 抛异常被 outer 捕获 → outer 结束时 UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only;行 (空) NEVER 外有事务、inner 抛异常被 outer 捕获 → outer 正常结束,行 outer
加入外层事务的会让外层提交时抛 UnexpectedRollbackException;REQUIRES_NEW 与 NESTED 只回滚自己。
REQUIRED 外面没有事务 → 行 outer+inner;inner 事务活跃=true,inner 连接 18 REQUIRES_NEW 外面没有事务 → 行 outer+inner;inner 事务活跃=true,inner 连接 18 NESTED 外面没有事务 → 行 outer+inner;inner 事务活跃=true,inner 连接 18 SUPPORTS 外面没有事务 → 行 outer+inner;inner 事务活跃=false,inner 连接 18 NOT_SUPPORTED 外面没有事务 → 行 outer+inner;inner 事务活跃=false,inner 连接 18 MANDATORY 外面没有事务 → ✗ IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' NEVER 外面没有事务 → 行 outer+inner;inner 事务活跃=false,inner 连接 18
REQUIRED、REQUIRES_NEW、NESTED 新开事务,SUPPORTS、NOT_SUPPORTED、NEVER 无事务执行,MANDATORY 抛异常。