@Transactional 失效的 8 个场景——90% 的 Java 开发者都踩过至少一个
引言 上季度有个资金对账任务出了个诡异 bug:扣款和加款两条 SQL,一条提交了,另一条抛异常没执行——钱少扣了,账不平了。排查了半天,最后发现原因是同事为了"复用代码",把事务方法从订单 Service 拆到了另一个类里,然后通过 this.xxx() 调用——事务悄悄失效了,代码没有任何报错,测试全绿。 @Transactional 的失效是最阴险的一类 bug:它不会报错、不会抛异常、甚至大部分场景连日志都没有,只是在你以为有事务的时候,实际上每条 SQL 都在自动提交。平时没事,等出问题就是数据不一致级别的故障。 这篇文章把 8 个失效场景一次讲全。每个场景给三样东西:能跑的失效代码、背后原理、最小修复方案。先给一张总览表,读者可以对照自查: #场景失效本质频率 1非 public 方法代理只增强 public 方法高 2同类内部调用 this.xxx()调用绕过了代理对象极高 3异常被 catch 吞掉代理看不到异常,无法触发回滚高 4rollbackFor 没配对默认只回滚 RuntimeException/Error高 5多线程事务绑定 ThreadLocal ....