一、事务失效的 7 大核心场景
1. 注解标注在非 public 方法上
- 失效原因:Spring 事务基于 AOP 动态代理实现,而代理机制仅对 public 方法生效。若将 @Transactional 加在 private/protected/ 默认权限(default)方法上,Spring 不会识别该注解,事务直接失效。
- 解决方案:确保加 @Transactional 的方法为 public 权限,且避免用 final/static 修饰(CGLIB 代理无法处理)。
2. 同类内部方法互相调用
- 失效原因:A 方法调用同一个类中的 B 方法(B 加 @Transactional),调用时走的是 this 原对象,而非 Spring 生成的代理对象,注解无法被解析,事务失效(最易踩坑的场景之一)。
- 解决方案:
- 方案 1(推荐):将 B 方法抽离到独立的 Service 类中,通过注入调用;
- 方案 2:在当前类中注入自身代理对象(如通过 ApplicationContext 获取),用代理对象调用 B 方法;
- 方案 3:使用 AspectJ 静态代理替代默认动态代理(成本较高,不推荐)。
3. 异常被捕获且未抛出 / 未指定回滚类型
- 失效原因:
- Spring 事务默认仅对 RuntimeException 和 Error 触发回滚,普通 Exception 不回滚;
- 开发中常出现 try-catch 捕获异常后仅打日志不抛出自定义异常,事务感知不到异常,直接提交(典型案例:转账业务中异常被吞,导致单边扣钱)。
- 解决方案:
- 方案 1:catch 块中手动抛出运行时异常(如 throw new RuntimeException(e));
- 方案 2:注解指定回滚所有异常:@Transactional(rollbackFor = Exception.class);
- 方案 3:catch 块中手动触发回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();。
4. 事务传播机制配置错误
- 失效原因:@Transactional 的 propagation 参数(默认 REQUIRED:有事务则加入,无则新建)若配置错误,会导致事务逻辑异常:
- 配置 REQUIRES_NEW:内层事务独立提交,外层回滚时内层已提交,数据不一致;
- 配置 NOT_SUPPORTED:直接禁用事务,所有操作无事务保护;
- 配置 NEVER/SUPPORTS 等不符合业务预期的传播级别。
- 解决方案:不懂传播机制时保持默认 REQUIRED,仅在明确需要 “嵌套事务”“独立事务” 时调整,且需充分测试。
5. 数据库引擎不支持事务
- 失效原因:MySQL 的 MyISAM 引擎不支持事务,仅 InnoDB 支持;若表引擎为 MyISAM,即便注解配置正确,事务也完全失效(老项目高频坑点)。
- 解决方案:
- 检查表引擎:SHOW CREATE TABLE 表名;;
- 将表引擎改为 InnoDB:ALTER TABLE 表名 ENGINE = InnoDB;;
- 新项目初始化时统一指定引擎为 InnoDB(如 MySQL 8.0 后默认 InnoDB,可忽略)。
6. 多数据源未指定事务管理器
- 失效原因:项目配置多数据源时,@Transactional 默认绑定主数据源的事务管理器,若操作从库 / 其他数据源且未指定对应事务管理器,事务无法生效(微服务架构高频问题)。
- 解决方案:注解中指定事务管理器:
@Transactional(transactionManager = "slaveTransactionManager")
7. 类未被 Spring 容器管理
- 失效原因:
- 类未加 @Service/@Component/@Repository 等注解,未被 Spring 扫描并创建代理对象;
- 手动 new 对象(如 new UserService()),而非通过 Spring 注入,导致注解无法被解析。
- 解决方案:
- 确保事务类被 Spring 注解标记,且在扫描包范围内;
- 所有对象通过 @Autowired/@Resource 注入,禁止手动 new 事务类。
二、事务失效快速排查技巧
1. 日志排查(最有效)
在 application.yml/application.properties 中开启事务 debug 日志,可清晰看到事务的开启、提交、回滚过程:
logging:
level:
org.springframework.transaction: DEBUG
org.springframework.jdbc.datasource.DataSourceTransactionManager: DEBUG
日志中出现 Creating new transaction 表示事务生效,无该日志则说明事务未触发。
2. 快速自检清单
三、面试高频回答思路
若面试被问及 “Spring 事务失效场景”,可按以下逻辑回答:
总结
Spring 事务失效的核心根源是代理对象未被正确触发或配置不符合 Spring 事务规则,其中 “内部调用” 和 “异常被吞” 是最高频坑点。开发时只需严格遵循上述 7 条规则,90% 的事务问题可提前规避;排查时优先开启 debug 日志,结合自检清单,可快速定位问题根源。


