前言做后端开发这么久事务失效绝对是我遇到过最隐蔽、最坑人的问题之一。很多新手包括我刚入行的时候总觉得给方法加个 Transactional注解就万事大吉了数据库操作肯定能回滚。但现实是线上经常出现部分数据插入成功、部分报错没回滚的情况排查半天找不到原因日志也看不出明显问题。我前前后后在项目里踩过十几次事务失效的坑整理出了8个真实高频场景都是工作中实打实遇到的问题每个都附带上可直接落地的解决方案看完基本能搞定99%的SpringBoot事务问题。一、最常见异常不是 RuntimeException事务不回滚这是90%的人第一次踩坑的原因。默认情况下Spring 的事务注解 Transactional只对运行时异常RuntimeException和错误Error生效。如果你的方法里抛出的是普通检查异常 Exception事务根本不会触发回滚。我之前写代码习惯性直接 throw new Exception()结果线上报错了数据照样入库直接造成数据不一致问题。解决办法手动指定回滚异常类型直接注解上配置即可Transactional(rollbackFor Exception.class)全局捕获所有异常不管是运行时还是检查异常统一触发回滚一劳永逸。二、同一个类中方法内部调用事务直接失效这个坑特别隐蔽新手基本都不懂底层原理。Spring 事务是基于 AOP 动态代理实现的只有外部调用当前类的方法才会走代理、触发事务拦截。如果是同一个类里A方法调用本类加了事务的B方法不会经过代理对象事务直接失效。我之前在工具类里嵌套调用测试环境好好的线上直接翻车排查了整整一下午。解决办法把事务方法抽离到新的 Service 类中外部调用或者通过 AopContext.currentProxy() 获取当前代理对象再调用方法。三、方法权限不是 public事务不生效Spring AOP 代理只支持 public 修饰的方法。如果你的事务方法是 private、protected、default 权限哪怕加了注解也完全不会生效。我之前重构代码时顺手改了方法权限没注意事务问题直接出了线上bug。解决办法所有需要事务的业务方法统一设置为 public 权限。四、方法内部手动 try-catch 捕获了异常很多人为了保证程序不崩会在事务方法里 try-catch 所有异常。但如果捕获异常后没有重新抛出Spring 感知不到报错就会认为程序正常执行不会回滚事务。这也是高频翻车点看似代码健壮实则暗藏数据风险。解决办法catch 捕获异常后手动抛出异常触发回滚或者手动设置事务回滚标记TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();五、数据库引擎不支持事务很多本地测试用的老表引擎还是 MyISAM。MyISAM 引擎不支持事务、不支持回滚只有 InnoDB 支持。哪怕你注解加的再对引擎不对一切白搭。解决办法核对数据库表引擎统一修改为 InnoDB。六、事务传播机制使用不当Spring 七种事务传播机制很多人只会用默认的。如果父方法无事务子方法配置了 SUPPORTS、NOT_SUPPORTED 等会导致子方法事务失效。尤其是嵌套业务场景传播机制选错大概率出问题。解决办法核心业务增删改方法统一使用 REQUIRED保证事务生效。复杂嵌套场景手动根据业务调整传播机制。七、多线程场景下事务失效主线程开启事务新线程中执行数据库操作无法共享主线程事务。线程是独立的事务上下文子线程报错主线程不会回滚极易造成数据错乱。解决办法多线程批量操作拆分事务不要共用主线程事务做好异常单独处理。八、只读事务、超时配置导致的隐性失效部分场景配置了 readOnly true只允许查询操作执行增删改会直接事务失效。还有事务超时时间设置过短业务没执行完事务自动超时回滚很多人误以为是代码bug。最后总结SpringBoot 事务失效99%都不是框架bug都是代码写法不规范。工作中只要避开上面8个坑基本不会再遇到事务不回滚的问题。建议大家收藏下次排查事务问题直接对照排查省时省力。后续会更新事务隔离级别、线上事务调优的实战内容感兴趣可以关注一波