分布式事务Seata
之前一直只是使用@GlobalTransactional 注解在业务方法上,但是没有从底层去了解,今天花一点时间更新一下Seata分布式事务。
首先是框架回滚做了什么
1.AT模式
核心一句话:**一阶段提前提交业务 SQL,同时存 undo_log 快照;二阶段回滚就是用 undo_log 里的前镜像做补偿 SQL 还原数据
✅ 一阶段:Prepare(准备)
关键点:业务数据 和 undo_log 在同一个本地数据库事务内一起提交
- RM 代理拦截业务 SQL,执行 SQL 前查询修改前数据:
beforeImage(前镜像) - 执行业务 SQL(update/insert/delete)修改业务表
- 执行 SQL 后查询修改后数据:
afterImage(后镜像) - 将
beforeImage、afterImage、xid、branchId写入undo_log 回滚日志表 - 业务数据变更 + undo_log,在同一个本地事务一起提交到数据库
- 向 TC 申请该行数据的全局锁;拿到锁成功,本地数据库锁、数据库连接直接释放
- RM 上报 TC:本分支一阶段执行成功
✅ 二阶段有两种分支结果:全局提交 / 全局回滚
1)全局提交(正常成功)
- TM 通知 TC:全局事务提交
- TC 下发 commit 指令给各个 RM 分支
- RM 收到 commit:只删除本分支对应的 undo_log 记录,不需要修改业务数据
- 官方特性:二阶段提交异步化,非常快,不阻塞业务。
2)全局回滚(分支异常、抛出异常、事务超时)
- TM 通知 TC 执行全局回滚
- TC 向所有参与的 RM 下发 rollback 指令
- RM 根据
XID+branchId查询 undo_log 快照 - 脏写校验:拿 undo_log 里面保存的
afterImage和 当前数据库真实数据对比- 相等:期间没有别的事务修改这条记录,可以安全补偿回滚
- 不相等:发生脏写,Seata无法自动回滚,输出告警,需要人工介入处理
- 根据 beforeImage 自动生成反向补偿 SQL
- update → 反向 update 还原旧值
- insert → delete 删除新增数据
- delete → insert 把旧数据插回去
- 在全新的本地数据库事务中执行补偿 SQL + 删除 undo_log,保证这两步原子性
- RM 把回滚结果上报 TC
补偿 SQL 执行会做幂等,TC 会重试 rollback 指令,不怕网络抖动重复下发。
Seata AT 模式:非侵入式分布式事务,业务几乎不用改代码,只加注解,底层代理 JDBC 数据源实现
- 业务不能直接使用原生
DataSource,必须被 Seata 的 DataSourceProxy 包装 - 代理拦截 JDBC 的增删改 SQL(insert/update/delete),自动做三件事:
- 查询数据快照(beforeImage、afterImage)
- 写入 undo_log 回滚日志
- 校验、抢占全局锁
- 业务代码不需要手写任何回滚逻辑,全部代理层自动完成。
MyBatis、JdbcTemplate、MyBatis‑Plus 都可以直接兼容,不需要改 DAO。
隐含坑点:
- undo_log 必须和业务表同一个库,否则本地事务失效;
- 数据源忘记包装 DataSourceProxy,分布式事务直接失效;
- 本地
@Transactional和@GlobalTransactional可以一起用,本地事务嵌套在分布式分支里; - XID 必须跨服务传递,自定义 http 调用需要手动传递 XID,Feign/Dubbo 自动处理;
- 二阶段回滚出现脏写报错,业务无法自动恢复,需要告警人工修复;
- TC(Seata‑Server)建议集群部署保证高可用。
2. TCC 模式(Try-Confirm-Cancel)
✅ 没有 undo_log!完全没有快照表
✅ 回滚载体:你自己编写的 cancel() 方法
✅ 回滚执行者:Seata 框架调用你写的 Cancel 接口
✅ 流程:
- Try:预留资源(冻结余额、锁定库存)
- Confirm:确认提交(真正扣减)
- Cancel:回滚释放资源(解冻、释放库存)
✅ 特点:业务侵入高,所有补偿逻辑自己写
✅ 要自己解决三大经典问题:空回滚、悬挂、幂等
✅ 优势:不受数据库限制,可以对接外部支付、第三方接口、不支持 AT 的存储
举例子:Try 冻结 100 元;全局失败 → 调用 Cancel 把冻结金额释放回去
3. SAGA 模式(长事务模式)
✅ 也没有 undo_log,也没有 Try
✅ 模型:一串正向业务步骤 + 每一步配套一个补偿接口
✅ 回滚载体:预先定义好的 compensation 补偿接口
✅ 回滚执行者:Seata 编排器,反向依次执行补偿接口
正向:A → B → C
如果 C 失败,回滚顺序:C 补偿 → B 补偿 → A 补偿(逆序)
✅ 适合:流程很长、跨很多异构服务、耗时久的业务(订单履约、物流)
✅ 缺点:没有锁机制,隔离性差,容易并发脏数据;补偿逻辑业务开发负责
4. XA 模式
✅ 不需要 undo_log,不需要业务写补偿代码
✅ 回滚载体:数据库原生 XA 事务能力
✅ 回滚执行者:数据库本身
✅ 流程:
- 一阶段 prepare:数据库锁住资源,不提交
- TC 通知回滚 → 数据库执行原生 rollback
✅ 优点:强一致,数据库原生保证
✅ 缺点:一阶段持有数据库锁、连接,性能差;数据库必须支持 XA 协议

浙公网安备 33010602011771号