Seata AT 模式实现无侵入分布式事务,核心是通过JDBC代理自动拦截SQL、生成undo_log并依托XID全局协调;需配置undo_log表、Seata数据源代理及注册中心,且不支持复杂SQL与DDL。

Java 中用 Seata AT 模式解决微服务多库分布式事务,核心在于“不改业务 SQL、不手动写补偿、不侵入原有逻辑”。它靠框架自动拦截 SQL、生成回滚日志、协调跨库操作,真正实现事务边界由注解划定,其余全由 Seata 托管。
AT 模式怎么做到无侵入
关键不是业务代码里加 try-catch 或手动回滚,而是靠 Seata 的 JDBC 数据源代理和 SQL 解析能力:
- 业务代码照常写 MyBatis/MyBatis-Plus 的 CRUD,SQL 不做任何改造
- 引入
seata-spring-boot-starter后,Seata 自动包装你的数据源,所有 SQL 都经其代理执行 - 执行前抓取“before image”(旧值),执行后抓取“after image”(新值),合并成
undo_log写入本地数据库 - 整个过程在同一个本地事务内完成——业务更新 + 回滚日志写入,原子提交或回滚
多库事务怎么串联起来
跨多个微服务、多个数据库的事务,靠全局事务 ID(XID)贯穿全程:
- 入口服务(如订单服务)加
@GlobalTransactional注解,Seata TC 就会生成唯一 XID 并透传给下游 - 下游服务(如库存、账户服务)使用 Seata 代理的数据源时,自动识别 XID,注册为分支事务
- 各服务各自在本地库执行 SQL + 写 undo_log,彼此独立但归属同一全局事务
- TC 根据 TM 提交/回滚指令,统一通知所有 RM:提交则异步清理日志;回滚则用 undo_log 反向生成 SQL 还原数据
必须做的基础配置项
少了任一环节,AT 模式就无法生效:
立即学习“Java免费学习笔记(深入)”;
- 每个参与事务的数据库,都得建好
undo_log表(Seata 官方提供建表语句,MySQL/Oracle 等略有差异) - 各服务的
application.yml中配置 Seata 服务地址(seata.registry.type=nacos等)、事务分组名(seata.tx-service-group=my_test_tx_group) - 数据源必须是 Seata 包装后的类型,例如 Spring Boot 下用
io.seata.rm.datasource.DataSourceProxy替代原生 HikariCP - 确保 Nacos(或其它注册中心)与 Seata Server 正常通信,TC 能实时感知各 RM 的注册状态
常见踩坑点提醒
看似简单,但实际落地时容易卡在这几个地方:
- SQL 不支持:复杂视图、存储过程、批量 insert…select、DDL 语句会被 Seata 拦截报错,需规避或换 TCC
- 隔离性限制:AT 默认读未提交(Read Uncommitted),若业务要求强隔离,需配合全局锁或应用层控制
- undo_log 表缺失或字段类型不匹配(比如 MySQL 的
blob字段被误建为text),会导致回滚失败 - Feign 调用未传递 XID:要确认 OpenFeign 拦截器已启用 Seata 的上下文传播(
seata.enable-auto-data-source-proxy=true)


















