Spring 事务传播行为+实战场景+避坑指南

张开发
2026/6/9 7:58:38 15 分钟阅读
Spring 事务传播行为+实战场景+避坑指南
一、先搞懂Spring 事务传播机制到底解决什么场景ServiceA.methodA() 调用 ServiceB.methodB()两个方法都加了Transactional问题谁的事务生效异常了谁回滚要不要共用一个事务事务传播行为 定义 方法之间调用时事务如何传递二、Spring 7 大事务传播行为Spring 定义在Propagation枚举里publicenumPropagation{REQUIRED,// 最常用默认SUPPORTS,MANDATORY,REQUIRES_NEW,// 高频NOT_SUPPORTED,NEVER,NESTED;// 嵌套事务}三大分类支持当前事务有就用没有就建不支持当前事务有也挂起不用嵌套事务子事务可独立回滚三、7 大传播行为 图解 场景 实战1REQUIREDSpring 默认90% 业务用这个有事务 → 加入没事务 → 创建新事务同生共死一个回滚全回滚场景订单创建 扣库存必须一起成功/失败调用关系A(REQUIRED) 调用 B(REQUIRED)同一个事务异常结果B 抛异常 → A、B 都回滚A 抛异常 → A、B 都回滚2REQUIRES_NEW创建新事务当前事务挂起无论有没有事务都新建独立事务A 和 B 事务完全隔离B 回滚不影响AA回滚不影响B场景日志记录失败不能影响主流程发送消息/通知子任务独立提交调用A(REQUIRED) 调用 B(REQUIRES_NEW)两个独立事务异常结果B 异常回滚 → A 可以捕获继续提交A 异常回滚 → 不影响 B 已提交的数据3NESTED嵌套事务Savepoint 机制子事务可以独立回滚有事务 → 创建嵌套子事务没事务 → 像 REQUIRED 一样新建父事务回滚 → 子事务必回滚子事务回滚 → 父事务可以继续执行场景子步骤失败不希望整个流程失败特点不是独立事务依赖主事务4SUPPORTS有事务就加入没有就以非事务运行场景查询方法可事务可不事务5MANDATORY强制必须有事务没有就直接抛异常场景强制该方法必须在事务内执行防止误调用6NOT_SUPPORTED不支持事务当前事务挂起以非事务运行7NEVER强制非事务存在事务就抛异常四、最核心的 3 个1. REQUIRED同生共死2. REQUIRES_NEW独立隔离3. NESTED嵌套可回滚五、源码底层原理深度解析Spring 事务核心类PlatformTransactionManager TransactionSynchronizationManager1. 事务挂起/恢复 源码逻辑// 简化版源码逻辑if(传播行为REQUIRES_NEW){// 挂起旧事务ObjectsuspendedResourcessuspend(transaction);try{// 创建新事务returnstartTransaction();}finally{// 恢复旧事务resume(suspendedResources);}}2. 事务传递本质ThreadLocal 保存当前事务连接TransactionSynchronizationManager.resources3. NESTED 底层使用 JDBCSavepointconnection.setSavepoint();六、实战最容易踩的 5 个坑坑1同类方法内调用事务失效ServicepublicclassOrderService{Transactionalpublicvoida(){b();// 同类内调用不经过代理 → 事务失效}Transactional(propagationREQUIRES_NEW)publicvoidb(){}}解决方案自己注入自己AopContext.currentProxy()坑2try-catch 导致事务不回滚Transactionalpublicvoida(){try{b();// b抛异常}catch(Exceptione){// 吞了异常 → 事务不回滚}}坑3REQUIRES_NEW 导致事务相互看不见B 是新事务A 未提交B查不到 A 的数据坑4NESTED 必须支持 JDBC 3.0 Savepoint不支持会自动降级为 REQUIRED坑5多线程调用事务完全不共享新线程 新事务和主线程无关七、实战指南业务场景怎么选1正常业务增删改REQUIRED默认2日志、消息、通知、子任务REQUIRES_NEW失败不影响主流程3子步骤可回滚主流程继续NESTED4查询方法SUPPORTS / 不加事务5必须在事务内运行MANDATORY八、一张表彻底记住传播行为有无事务关系回滚影响REQUIRED无则创建共用同一个一起回滚REQUIRES_NEWalways新建独立事务互不影响NESTED嵌套子事务父子关系子不影响父父影响子九、一句话终极总结REQUIRED共用事务同生共死REQUIRES_NEW独立事务互不干扰NESTED嵌套事务子可回滚父不回滚同类内调用、try-catch、多线程都会导致事务失效

更多文章