news 2026/7/16 14:29:48

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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:数据库层面实现 2PC,Prepare 阶段占用行锁直到全局提交 / 回滚,阻塞严重;
  • Seata AT:业务 SQL 执行直接提交本地事务,用快照 + 全局锁实现隔离,大幅降低锁持有时间。

2. 三大核心角色(和标准 2PC 一致)

  1. TC (Transaction Coordinator):事务协调器,独立服务(seata-server),记录全局事务、分支事务状态,下发提交 / 回滚指令。
  2. TM (Transaction Manager):事务发起方,业务服务,通过@GlobalTransactional开启全局事务。
  3. RM (Resource Manager):资源管理器,每个微服务的数据库代理,拦截 SQL、生成回滚日志、上报 TC、执行分支提交 / 回滚。

3. 必须依赖的业务表(每个业务库都要建)

sql

CREATE 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`) ) ENGINE=InnoDB;

undo_log:分支事务的回滚快照表,AT 模式核心。

4. 两个核心机制

  1. Undo Log 回滚快照:更新 / 删除前记录修改前数据,失败时恢复;
  2. 全局锁(Global Lock):解决分布式脏写,保证隔离性。

二、AT 完整两阶段流程(核心)

AT 同样分一阶段 Prepare、二阶段 Commit/Rollback,但和 XA 2PC 逻辑完全不同。 全局唯一标识:XID,TM 生成,所有微服务透传。

阶段一:一阶段提交(本地事务直接提交,核心优化点)

流程:TM 开启全局事务 → 各个 RM 执行业务 SQL,同步完成三件事:

  1. 前置镜像查询(Before Image)执行 Update/Delete 前,查询当前行所有字段,存入 undo_log 的 rollback_info。 例:update stock set num = num -1 where id = 1先查 id=1 的原始库存num=100,保存快照。

  2. 执行业务 SQL,提交本地事务直接执行更新,本地数据库事务立刻 commit,释放本地行锁! 这是和 XA 最大区别:XA Prepare 不提交、锁长期持有;AT 一阶段直接提交本地事务,本地锁马上释放,并发性能大幅提升。

  3. 后置镜像(After Image)+ 插入 undo_logSQL 执行后查询修改后数据,一并存入 undo_log,标记日志状态log_status=0(未处理)

  4. 向 TC 注册分支、申请全局锁RM 上报 TC:当前分支事务修改了哪些主键行,抢占全局锁

    • 全局锁作用:其他分布式事务不能修改同一行,防止脏写,实现读已提交隔离
    • 全局锁存储在 TC 内存,不是数据库锁,本地锁已经释放。
  5. 一阶段收尾 所有分支全部完成一阶段提交,TC 标记全局事务状态为committing,进入二阶段。

一阶段总结:本地事务已经落库,只是留存 undo_log,数据处于 “临时有效” 状态,依赖全局锁隔离其他事务。

阶段二:二阶段两种分支

分支 1:全局提交(所有分支一阶段成功)

TC 下发 commit 指令给所有 RM:

  1. RM 收到提交指令;
  2. 删除当前分支对应的 undo_log 记录(标记 log_status=1 或直接删除);
  3. 释放 TC 上持有的全局锁;
  4. 分支处理完成,通知 TC;
  5. TC 收到全部分支 ack,全局事务结束。

关键点:提交时不用改业务数据,只删回滚日志,极快,无数据库 IO 压力。

分支 2:全局回滚(任意分支一阶段失败 / 超时)

TC 下发 rollback 指令给 RM:

  1. RM 查询当前分支的 undo_log,取出 Before Image 修改前快照;
  2. 根据前置镜像反向补偿执行 SQL,恢复数据到修改前状态; 例:之前扣减库存 num-1,回滚执行update stock set num=100 where id=1
  3. 补偿 SQL 执行完成,本地事务提交;
  4. 删除 undo_log,释放全局锁;
  5. 回复 TC,全局事务终止。

故障兜底:如果回滚时 RM 宕机,重启后 RM 会主动向 TC 查询 XID 状态,自动重试回滚,保证幂等。


三、全局锁与隔离性(解决脏写)

1. 场景说明

事务 A(全局事务)一阶段更新库存 id=1,本地锁释放,但持有 TC 全局锁; 事务 B(另一个全局事务)也要更新 id=1:

  • B 一阶段执行 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 优缺点

优点

  1. 零业务代码侵入:只需要注解开启全局事务,不用手写补偿逻辑;
  2. 性能远优于 XA,本地锁快速释放,适合高并发微服务;
  3. 回滚自动兜底,故障重启自动恢复,保证最终一致性;
  4. 兼容所有支持 JDBC 的数据库(MySQL、Oracle、PostgreSQL 等)。

缺点

  1. 需要额外维护 undo_log 表,每次写操作多两次镜像查询(前置 + 后置),增加少量 SQL 开销;
  2. 仅保证读已提交隔离,存在不可重复读;
  3. 只支持 DML(Insert/Update/Delete),DDL 语句不支持;
  4. 长事务场景会长期占用 TC 全局锁,影响并发;
  5. 极端网络分区下,会短暂出现中间状态数据,属于最终一致性,非实时强一致。

六、典型业务流程示例(下单 + 扣库存)

服务 A:订单服务(TM,开启全局事务) 服务 B:库存服务(RM)

  1. TM 生成 XID,调用库存服务,XID 通过请求头传递;
  2. 库存 RM 一阶段: 查原库存快照 → 扣减库存、本地 commit → 写入 undo_log → 向 TC 申请全局锁;
  3. 订单 RM 一阶段: 插入订单快照 → 新增订单、本地 commit → 写入 undo_log → 注册分支;
  4. TC 收到两个分支全部成功,下发二阶段 commit;
  5. 订单、库存 RM 删除各自 undo_log,释放全局锁;
  6. 全局事务完成,数据永久生效。

异常场景:库存服务一阶段成功,订单服务抛异常: TC 收到失败信号,向库存 RM 下发 rollback; 库存 RM 读取 undo_log 前置镜像,恢复原始库存,删除日志。

七、关键补充:幂等与防悬挂

  1. 防悬挂二阶段回滚请求先到达 RM,一阶段 SQL 后到,会出现空回滚。 解决:回滚时先插入一条空 undo_log 占位,后续一阶段执行时发现已有 undo 记录,直接放弃执行业务 SQL,避免悬挂脏数据。
  2. 幂等保证TC 会重复下发 commit/rollback;RM 通过 xid+branch_id 唯一索引判断 undo_log 是否已处理,重复指令直接忽略,不会重复回滚 / 删除。

八、适用场景

  • 绝大多数电商、支付、供应链微服务,常规短事务;
  • 追求开发效率(无侵入)、并发性能; 不适合:超长事务、DDL 操作、要求可重复读隔离级别的场景。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 14:28:54

C/C++内存管理:从底层原理到RAII与智能指针实战

1. 项目概述:为什么C/C内存管理是程序员的“内功心法”干了这么多年C/C开发,我越来越觉得,内存管理这门手艺,就像武侠小说里的内功心法。招式(算法、数据结构)可以学得很快,但内功不扎实&#x…

作者头像 李华
网站建设 2026/7/16 14:28:12

Copilot企业版合规上线全路径(GDPR+等保2.0双认证实操手册)

更多请点击: https://codechina.net 第一章:Copilot企业版合规上线全景概览 Microsoft Copilot 企业版已于2024年正式通过ISO 27001、SOC 2 Type II、GDPR及中国《个人信息保护法》(PIPL)等多项全球主流合规认证,并面…

作者头像 李华
网站建设 2026/7/16 14:27:42

Rust在CH32V307嵌入式开发中的优势与实践

1. 为什么选择Rust进行CH32V307嵌入式开发?作为一名长期从事嵌入式开发的工程师,我最初接触Rust语言时也持怀疑态度。直到在CH32V307这款RISC-V芯片上实际验证后,才发现Rust带来的变革远超预期。传统嵌入式开发中,C语言的内存安全…

作者头像 李华
网站建设 2026/7/16 14:26:57

鸿蒙 ArkTS 实战:Fan Setting Library 从创作记录到状态反馈完整解析

鸿蒙 ArkTS 实战:Fan Setting Library 从创作记录到状态反馈完整解析 前言 Fan Setting Library 是一个面向 创作管理与灵感记录 的鸿蒙 ArkTS 小应用。记录创作条目、站点信息和提醒备注,适合日常创作复盘。 本文基于 entry/src/main/ets/pages/Index…

作者头像 李华
网站建设 2026/7/16 14:26:41

FREUDE弗莱德 FP-8V5 解析:四路DSP功放一体机如何服务原车音响升级

省流摘要FREUDE弗莱德 FP-8V5 是一款 8 路 DSP、4 路 D 类功放的车载 DSP 功放一体机,适合原车音响升级、前声场两分频、基础主动两分频以及后期增加有源低音或外置功放等场景。它提供 4 路高电平输入、2 路低电平输入、光纤、数字蓝牙、U盘和 OTG 播放,…

作者头像 李华