连载中 9/18

事务(下):失效的八种姿势

2026-11-06 · 34 阅读 · 0 评论 · 0 赞

失效八连,全是原理推出来的

有了第 6、8 篇的原理,失效场景不需要背表格——每一种都能指着机制推出来:

一、自调用:this 绕过代理,拦截器没机会上桌——开篇的标本,解法三条(@Lazy 自注入、拆类、exposeProxy)。

二、方法不是 public:Spring 事务切面只处理 public 方法,protected、包级、private 上的 @Transactional 被静默忽略——不报错、无警告,最阴的一种。

三、异常被 catch 吞了:拦截器靠「方法抛出异常」触发回滚,你把异常吃掉,它以为岁月静好照常 commit。非要 catch 就在块里调 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 标记回滚,或者重抛。

四、rollbackFor 没配:默认只回滚 RuntimeException 和 Error,受检异常照样提交——上篇讲过的默认规则坑。

五、对象不受容器管:自己 new 的 Service 没有代理,注解纯属装饰品。事务的前提是「从容器拿代理对象来用」。

六、传播行为配错:挂了 NOT_SUPPORTED 的方法以非事务方式执行;REQUIRES_NEW 的内外事务互相独立——想要「一起回滚」却配成了「各回各的」,第 10 篇细拆。

七、跨线程:事务上下文绑在 ThreadLocal 上,新开线程拿不到——异步方法里的数据库操作各用各的连接,永远不在同一个事务里。

八、存储引擎不支持:MySQL 的 MyISAM 引擎不支持事务,只有 InnoDB 支持——老项目迁移时的经典暗坑。

排查心法:三步定位

遇到「事务没生效」按顺序查:第一步,Bean 是不是容器管理的代理——AopUtils.isAopProxy(bean) 见分晓;第二步,调用路径是否经过代理——没有 this 自调用、方法是 public;第三步,异常是否真的飞出了事务方法边界——没被 catch、类型命中 rollbackFor。八种失效,九成死在这三步里。

单层事务说完了。多个事务方法嵌套调用时谁听谁的?传播行为七式,下一篇排兵布阵。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#Spring#事务失效#Transactional#Spring Boot

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10135 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9900 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9330 阅读 · 21 评论 · 287 赞