Seata AT 模式完整原理(无侵入改进版 2PC)

📅 2026/7/16 14:29:53
Seata AT 模式完整原理(无侵入改进版 2PC)
目录一、前置基础1. AT 定位2. 三大核心角色和标准 2PC 一致3. 必须依赖的业务表每个业务库都要建4. 两个核心机制二、AT 完整两阶段流程核心阶段一一阶段提交本地事务直接提交核心优化点阶段二二阶段两种分支分支 1全局提交所有分支一阶段成功分支 2全局回滚任意分支一阶段失败 / 超时三、全局锁与隔离性解决脏写1. 场景说明2. 隔离级别四、AT 对比 XA 2PC核心差异五、AT 优缺点优点缺点六、典型业务流程示例下单 扣库存七、关键补充幂等与防悬挂八、适用场景一、前置基础1. AT 定位AT Automatic Transaction自动事务模式是 Seata 最主流、无代码侵入的分布式事务方案底层是改良版二阶段提交 2PC规避了原生 XA 2PC 长锁、性能差的问题。原生 XA数据库层面实现 2PCPrepare 阶段占用行锁直到全局提交 / 回滚阻塞严重Seata AT业务 SQL 执行直接提交本地事务用快照 全局锁实现隔离大幅降低锁持有时间。2. 三大核心角色和标准 2PC 一致TC (Transaction Coordinator)事务协调器独立服务seata-server记录全局事务、分支事务状态下发提交 / 回滚指令。TM (Transaction Manager)事务发起方业务服务通过GlobalTransactional开启全局事务。RM (Resource Manager)资源管理器每个微服务的数据库代理拦截 SQL、生成回滚日志、上报 TC、执行分支提交 / 回滚。3. 必须依赖的业务表每个业务库都要建sqlCREATE TABLE undo_log ( id bigint AUTO_INCREMENT, branch_id bigint NOT NULL COMMENT 分支事务ID, xid varchar(128) NOT NULL COMMENT 全局事务ID, context varchar(128) NOT NULL, rollback_info longblob NOT NULL COMMENT 数据快照用于回滚, log_status int NOT NULL COMMENT 0正常 1已提交 2已删除, log_created datetime NOT NULL, log_modified datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY ux_undo_log (xid,branch_id) ) ENGINEInnoDB;undo_log分支事务的回滚快照表AT 模式核心。4. 两个核心机制Undo Log 回滚快照更新 / 删除前记录修改前数据失败时恢复全局锁Global Lock解决分布式脏写保证隔离性。二、AT 完整两阶段流程核心AT 同样分一阶段 Prepare、二阶段 Commit/Rollback但和 XA 2PC 逻辑完全不同。 全局唯一标识XIDTM 生成所有微服务透传。阶段一一阶段提交本地事务直接提交核心优化点流程TM 开启全局事务 → 各个 RM 执行业务 SQL同步完成三件事前置镜像查询Before Image执行 Update/Delete 前查询当前行所有字段存入 undo_log 的 rollback_info。 例update stock set num num -1 where id 1先查 id1 的原始库存num100保存快照。执行业务 SQL提交本地事务直接执行更新本地数据库事务立刻 commit释放本地行锁 这是和 XA 最大区别XA Prepare 不提交、锁长期持有AT 一阶段直接提交本地事务本地锁马上释放并发性能大幅提升。后置镜像After Image 插入 undo_logSQL 执行后查询修改后数据一并存入 undo_log标记日志状态log_status0未处理。向 TC 注册分支、申请全局锁RM 上报 TC当前分支事务修改了哪些主键行抢占全局锁。全局锁作用其他分布式事务不能修改同一行防止脏写实现读已提交隔离全局锁存储在 TC 内存不是数据库锁本地锁已经释放。一阶段收尾 所有分支全部完成一阶段提交TC 标记全局事务状态为committing进入二阶段。一阶段总结本地事务已经落库只是留存 undo_log数据处于 “临时有效” 状态依赖全局锁隔离其他事务。阶段二二阶段两种分支分支 1全局提交所有分支一阶段成功TC 下发 commit 指令给所有 RMRM 收到提交指令删除当前分支对应的 undo_log 记录标记 log_status1 或直接删除释放 TC 上持有的全局锁分支处理完成通知 TCTC 收到全部分支 ack全局事务结束。关键点提交时不用改业务数据只删回滚日志极快无数据库 IO 压力。分支 2全局回滚任意分支一阶段失败 / 超时TC 下发 rollback 指令给 RMRM 查询当前分支的 undo_log取出 Before Image 修改前快照根据前置镜像反向补偿执行 SQL恢复数据到修改前状态 例之前扣减库存 num-1回滚执行update stock set num100 where id1补偿 SQL 执行完成本地事务提交删除 undo_log释放全局锁回复 TC全局事务终止。故障兜底如果回滚时 RM 宕机重启后 RM 会主动向 TC 查询 XID 状态自动重试回滚保证幂等。三、全局锁与隔离性解决脏写1. 场景说明事务 A全局事务一阶段更新库存 id1本地锁释放但持有 TC 全局锁 事务 B另一个全局事务也要更新 id1B 一阶段执行 SQL 更新成功但去 TC 申请全局锁时发现已被 A 占用B 分支一阶段阻塞等待全局锁若 A 最终回滚 / 提交释放全局锁B 才能拿到锁完成注册若等待超时B 自动回滚本地修改。2. 隔离级别AT 默认读已提交不支持可重复读普通本地读可以读到其他全局事务一阶段提交的未确认数据写操作受全局锁控制不会出现脏写 如果需要可重复读使用 Seata 新的 AT 快照隔离模式或 TCC。四、AT 对比 XA 2PC核心差异对比项XA 2PCSeata AT一阶段行为执行 SQL不提交本地事务持有行锁执行 SQL直接提交本地事务释放行锁锁资源数据库行锁长期阻塞并发差本地锁快速释放仅 TC 全局锁短持有回滚方式数据库原生 undo 回滚业务前置镜像反向补偿更新二阶段开销提交 / 回滚都操作业务数据提交仅删 undo_log轻量代码侵入无数据库原生支持无仅加注解GlobalTransactional性能差高并发锁等待严重优秀互联网主流依赖数据库支持 XA业务库必须创建 undo_log 表五、AT 优缺点优点零业务代码侵入只需要注解开启全局事务不用手写补偿逻辑性能远优于 XA本地锁快速释放适合高并发微服务回滚自动兜底故障重启自动恢复保证最终一致性兼容所有支持 JDBC 的数据库MySQL、Oracle、PostgreSQL 等。缺点需要额外维护 undo_log 表每次写操作多两次镜像查询前置 后置增加少量 SQL 开销仅保证读已提交隔离存在不可重复读只支持 DMLInsert/Update/DeleteDDL 语句不支持长事务场景会长期占用 TC 全局锁影响并发极端网络分区下会短暂出现中间状态数据属于最终一致性非实时强一致。六、典型业务流程示例下单 扣库存服务 A订单服务TM开启全局事务 服务 B库存服务RMTM 生成 XID调用库存服务XID 通过请求头传递库存 RM 一阶段 查原库存快照 → 扣减库存、本地 commit → 写入 undo_log → 向 TC 申请全局锁订单 RM 一阶段 插入订单快照 → 新增订单、本地 commit → 写入 undo_log → 注册分支TC 收到两个分支全部成功下发二阶段 commit订单、库存 RM 删除各自 undo_log释放全局锁全局事务完成数据永久生效。异常场景库存服务一阶段成功订单服务抛异常 TC 收到失败信号向库存 RM 下发 rollback 库存 RM 读取 undo_log 前置镜像恢复原始库存删除日志。七、关键补充幂等与防悬挂防悬挂二阶段回滚请求先到达 RM一阶段 SQL 后到会出现空回滚。 解决回滚时先插入一条空 undo_log 占位后续一阶段执行时发现已有 undo 记录直接放弃执行业务 SQL避免悬挂脏数据。幂等保证TC 会重复下发 commit/rollbackRM 通过 xidbranch_id 唯一索引判断 undo_log 是否已处理重复指令直接忽略不会重复回滚 / 删除。八、适用场景绝大多数电商、支付、供应链微服务常规短事务追求开发效率无侵入、并发性能 不适合超长事务、DDL 操作、要求可重复读隔离级别的场景。