Seata分布式事务回滚需确保业务异常透出至GlobalTransactionalInterceptor,避免全局异常处理器吞掉异常;必须使用DataSourceProxy代理数据源并创建undo_log表;@GlobalTransactional须加在TM最外层非private/static/final方法上。

Spring Boot 中用 Seata 处理分布式事务时,全局业务异常(比如库存不足、余额不够)必须“透出”给 Seata 的拦截器,才能触发回滚。如果被全局异常处理器提前捕获并“吃掉”,Seata 就收不到异常,会误判为成功,导致事务提交、数据不一致。
确保异常能被 Seata 拦截到
Seata 的 @GlobalTransactional 是靠 GlobalTransactionalInterceptor 在方法执行后检查是否抛出了未被捕获的异常。只要异常没被上层吞掉,它就能介入回滚流程。
- 全局异常处理器(如
@RestControllerAdvice)的@ExceptionHandler方法不能在业务方法返回前就处理掉所有异常 - 特别要避免对
RuntimeException或自定义业务异常(如InventoryNotEnoughException)做泛化捕获并静默返回 - 建议只捕获明确不需要触发回滚的异常类型(如
IllegalArgumentException参数校验失败),其他异常应让其向上冒泡
手动触发回滚(兜底方案)
当某些场景必须统一捕获异常(比如统一日志、统一响应体),又不能影响事务状态时,可在异常处理器中主动通知 Seata 回滚:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 通过
RootContext.getXID()获取当前全局事务 ID - 调用
GlobalTransactionContext.reload(xid).rollback()强制回滚 - 注意:该操作需在事务上下文仍有效时执行(即还没离开 TM 方法栈),且需捕获
TransactionException
检查数据源是否被正确代理
Seata 必须通过 DataSourceProxy 拦截 SQL 才能生成 undo_log 并支持回滚。如果用了原始数据源,即使抛出异常,也没有回滚依据。
- 确认配置类中声明了
@Bean public DataSourceProxy dataSourceProxy(DataSource dataSource) - 确保业务代码中注入的是
DataSourceProxy,而不是原始DataSource - 检查数据库中是否存在
undo_log表,结构需与 Seata 1.4.2 要求一致
验证 @GlobalTransactional 注解使用正确
注解是事务入口,配置错误会导致 Seata 根本不介入。
- 必须加在发起方(TM)的最外层服务方法上,不能只加在被调用方(RM)
- 推荐显式指定
timeout和name,便于排查和监控 - 方法不能是
private、static或final,否则 Spring AOP 无法代理

















