Seata AT 模式实现原理

distributed-transaction 📚 learning seata-at · distributed-transaction · seata · at-mode · global-lock · undo-log · tc · tm · rm · xa · cloud-native

TL;DR(30 秒扫完)

  • 三角色:TC(Seata Server,协调全局事务)+ TM(业务应用代理)+ RM(代理 DataSource)
  • 一阶段:拦截 SQL → 读 before image → 执行业务 SQL → 读 after image → 同本地事务写 undo_log → 申请全局锁 → 本地提交
  • 二阶段成功:异步删除 undo_log;二阶段失败:读 undo_log → 生成反向 SQL → 本地回滚
  • 全局锁是灵魂:一阶段释放本地锁但保留全局锁到二阶段结束,防止中间态被改
  • 与 2PC 关键区别:一阶段提交后释放本地锁,参与者不阻塞
  • 性能瓶颈:全局锁按行加锁,高并发同一行会串行化

关键结论

结论 AAT 模式的灵魂是全局锁——一阶段释放本地锁但保留全局锁,让事务不阻塞
结论 Bundo_log 是回滚的依据,存 before/after image(JSON 格式)
结论 C代理数据源让业务代码完全无感,框架自动拦截 SQL
结论 D全局锁是高并发场景的性能瓶颈,需要换 TCC 才能解决

完整讲解(费曼四步)

STEP 1 · 概念

Seata AT 模式:Apache Seata 提供的"自动补偿"分布式事务模式,框架代理数据源,业务代码基本不用改,靠 undo_log 实现自动回滚。

STEP 2 · 大白话

单机事务类比:你去银行柜台办业务,柜员帮你把所有步骤办完,你不用管中间过程——引擎自己保证。 Seata AT 类比:你同时要办"开户+转账+理财"三件事,分别找三个柜员。AT 模式相当于有一个"协调秘书":
  • 秘书让三个柜员各自先把业务"预演"一遍(读 before image → 执行 → 读 after image),并把"操作记录"写下来(undo_log)
  • 秘书同时给每个柜员的业务盖一个"全局章"(全局锁),防止别人在中间修改
  • 如果三个柜员都说"没问题",秘书让所有人正式提交,然后把操作记录删掉
  • 如果有一个柜员说"有问题",秘书让所有人按操作记录"反向操作"回滚

STEP 3 · 底层

三角色架构

角色英文职责实现
TCTransaction CoordinatorSeata Server,协调全局事务,维护全局事务状态Seata Server 进程
TMTransaction Manager业务应用内的代理,发起全局事务、决定提交或回滚业务应用中的代理类
RMResource Manager代理 DataSource,管理分支事务,与 TC 通信JdbcProxy 拦截 SQL

AT 模式两阶段流程

一阶段(本地事务阶段):
  业务 SQL 执行:
    1. 拦截 SQL,读取业务数据前镜像(before image)
    2. 执行业务 SQL
    3. 读取业务数据后镜像(after image)
    4. 在同一本地事务内:业务 SQL + 写 undo_log(存 before/after image)
    5. RM 向 TC 申请**全局锁**(行级锁)
    6. 本地事务提交(业务数据和 undo_log 一起落盘)

二阶段(全局事务阶段):
  成功路径:TC 让各 RM 异步删除 undo_log
  失败路径:TC 让各 RM 读 undo_log,反向生成回滚 SQL,本地事务回滚

全局锁的作用(AT 模式的灵魂)

  • 目的:防止一阶段提交后、二阶段提交前,其他事务修改了同一行数据
  • 实现:基于行级锁,TC 记录 lock_record 表
  • 代价:全局锁存在期间,同一行不能有其他事务修改,影响并发性能
  • 关键区别:一阶段提交后本地锁释放(不阻塞本地事务),但全局锁保留到二阶段结束

undo_log 的作用

  • Seata 框架自动创建的表(业务需手动建表,DDL 见官方文档)
  • 存 before/after image(JSON 格式)
  • 回滚时框架自动读取 undo_log,生成"反向 SQL"(如 UPDATE t SET col = 'old_value' WHERE id = 1)

代理数据源的无感机制

  • 业务配置 SeataDataSourceProxy 替换原 DataSource
  • 所有 SQL 都被 JdbcProxy 拦截
  • 业务代码完全无感知

与 2PC / TCC / XA 的对比

维度2PC/XASeata ATTCC
侵入性低低高
一致性强强强
阻塞会不阻塞(一阶段后释放本地锁)不阻塞
锁机制行锁(数据库级)全局锁(Seata 级)业务锁
回滚方式数据库 redo logundo_log(业务层)业务代码

全局锁性能瓶颈

  • 全局锁按行加锁,一阶段提交后立即释放本地锁但保留全局锁到二阶段结束
  • 高并发同一行会串行化
  • 优化方案:缩短事务、批量提交、换 TCC(TCC 的锁是业务层自己实现的,粒度更细)

生产部署要点

  • 建好 undo_log 表
  • 配好 Seata Server 高可用(多 TC 实例 + 注册中心)
  • 监控全局锁占用情况
  • 设置事务超时时间(默认 15 分钟)
  • 避免 TC 故障导致事务长期悬挂

STEP 3.5 · 与 2PC / XA 的深度对比(AT 对 2PC 的三大关键改进)

AT 不是"2PC 的补丁",而是重新拆两阶段——一阶段业务已经提交,二阶段只做日志清理或补偿。这是 AT 在微服务/云原生场景下的核心竞争力。

XA 在微服务架构下的六大工程挑战

XA 是 2PC 的具体实现(MySQL 提供 XA START/PREPARE/COMMIT 语法),在微服务场景下有六大痛点:
#挑战说明工程后果
1会话耦合XA 事务要求事务内保持同一 DB 连接跨服务不同 DB 实例无法天然延伸
2长事务阻塞PREPARE 到 COMMIT 期间所有参与者行锁+连接都被持有,跨网络调用可能持续秒级/几十秒连接池打满,QPS 上不去
3协调者阻塞TC 在 Prepare 之后 Commit 之前崩溃,RM 进入"不确定状态"(2PC 经典问题)事务永久悬挂
4性能瓶颈所有参与者 DB 连接在整个事务期间不释放QPS 差
5跨库兼容Oracle/PostgreSQL/SQL Server 的 XA 实现不完全一致微服务异构场景难统一
6扩展性差单个 XA 事务 RM 数量通常不超过 3-4 个跨多个微服务的链路覆盖不了
本质问题:XA 是"两阶段都要执行操作"——一阶段加锁不提交,二阶段提交或回滚。所有参与者的资源在整个事务期间都被占用。

Seata AT 相对 2PC 的三大关键改进

维度2PC / XASeata AT关键差异
一阶段动作加锁 + 不提交业务提交 + undo_logAT 一阶段业务已经提交,本地锁立即释放
二阶段动作提交或回滚(执行操作)清理或补偿(读 undo_log)AT 二阶段是记账,不再执行操作
回滚方式TC 通知 RM 反向操作读 undo_log 生成反向 SQLAT 回滚基于日志,业务方完全不参与
锁粒度数据库行锁全程持有业务本地事务提交后释放,TC 侧逻辑锁AT 全局锁只在跨全局事务冲突检测时使用
业务侵入低(配置 XA)更低(配置代理数据源即可)业务代码不用改一行
核心洞察:AT 的两大创新——
  • 两阶段拆分解耦:一阶段"业务提交",二阶段"日志清理",与 2PC "两阶段都执行操作"完全不同
  • 基于日志的自动补偿:不需要业务方参与回滚,TC 读 undo_log 自动生成反向 SQL
云原生适配能力(AT 相对 XA 的额外优势):
维度说明
TC 无状态可水平扩展K8s Operator 部署,多 TC 实例通过 Raft 或共享存储协调
RM 无状态可重启业务进程重启后,TC 通过事务回查机制恢复未完成事务
支持多种资源不只是 MySQL,还有 Redis / RocketMQ / Kafka 等适配
业务无侵入JDBC 代理自动拦截 SQL,业务代码不用改
容器化友好官方 K8s Operator,通过 service discovery 找 TC

AT 的局限(选型时必须知道)

  • 热点行场景全局锁竞争严重:全局锁按行加锁,高并发同一行串行化
  • 非事务性操作无法覆盖:RPC 调用(发消息、发邮件)需要额外的 TCC 或事务消息
  • 依赖数据库唯一索引:全局锁基于数据库行锁,需要业务表有合理的主键/索引
  • 主要面向 Java 生态:非 Java 服务支持较弱
  • 不适合跨语言异构:跨语言需自行实现事务回查

工程选型建议

  • 主链路强一致(订单+库存) → Seata AT 或 TCC
  • 核心账务(扣款+入账) → TCC 或 XA
  • 副链路最终一致(通知/积分/风控) → 事务消息 / 本地消息表
  • 跨 RPC 调用 → 事务消息 / TCC(AT 覆盖不了)

STEP 4 · 简化

一句话总结:Seata AT = 代理数据源 + undo_log + 全局锁,让业务代码无感地享受分布式事务;全局锁是灵魂但不阻塞,高并发场景换 TCC。

常见误区

"AT 模式不需要全局锁"
全局锁是 AT 模式的灵魂,没有它就无法保证一致性
"AT 模式和 2PC 一样会阻塞"
AT 一阶段提交后释放本地锁,不阻塞本地事务;2PC 是全程持锁
"undo_log 是数据库自带的"
undo_log 是 Seata 框架自定义的表,业务需手动建表
"AT 模式完全无侵入"
AT 模式侵入性低(业务代码不用改),但仍需配置代理数据源和建 undo_log 表
"Seata 叫 STAY"
Seata(Apache 项目,S-e-a-t-a)
"AT 模式是保持会话"
AT 的核心是业务无侵入 + 全局锁 + undo log 自动补偿,与"保持会话"(那是 XA)完全不同
"AT 模式不需要 undo_log"
undo_log 是 AT 二阶段回滚的唯一依据,没有 undo_log 就无法做反向 SQL 补偿
"XA 在微服务下可以直接用"
XA 在微服务下有 6 大挑战(会话耦合、长事务阻塞、协调者阻塞、性能瓶颈、跨库兼容、扩展性差),工程上被 Seata AT/TCC 替代
"AT 的三大改进只是加了事务"
AT 相对 2PC 的三大改进是两阶段拆分解耦(一阶段业务提交+undo_log、二阶段清理/补偿)+ 基于日志自动补偿(业务方不参与回滚)+ 全局锁优化锁粒度(业务提交后释放本地锁)

关联题目

  • ⚠️ 《Seata 的 AT 模式的实现原理》— 2026-09-23 Round 2 Q5, ⭐⭐, 完全没概念,只知"强一致+undo log"
  • ⚠️ 《MySQL 的 XA 事务在微服务架构中的挑战 & Seata AT 对 2PC 的关键改进》— 2026-10-10 Round 1 Q9, ⭐⭐, 直接说"不了解 Seata AT",猜测 AT 是"保持会话"

关联知识

代理数据源 + undo_log + 全局锁,业务无感享受分布式事务
协调秘书让柜员预演业务、写操作记录、盖全局章,成功后删记录,失败后按记录反向操作
✦ 记 忆 口 诀 ✦
全局锁是灵魂 / 一阶段释放本地锁 / 高并发换 TCC
关键可视化
Seata AT 三角色架构
flowchart LR
  A[业务应用] --> TM[TM Transaction Manager]
  TM --> TC[TC Transaction Coordinator Seata Server]
  A --> RM[RM Resource Manager]
  RM --> TC
  TC --> RM
  TC -->|协调全局事务| TM
AT 一阶段流程
flowchart TB
  A[业务 SQL] --> B[RM 拦截 SQL]
  B --> C[读 before image]
  C --> D[执行业务 SQL]
  D --> E[读 after image]
  E --> F[同本地事务写 undo_log]
  F --> G[向 TC 申请全局锁]
  G --> H[本地事务提交]
  H --> I[释放本地锁 保留全局锁]
AT 二阶段流程
flowchart TB
  A[二阶段] --> B{TC 决定}
  B -->|成功| C[异步删除 undo_log]
  B -->|失败| D[读 undo_log]
  D --> E[生成反向 SQL]
  E --> F[本地事务回滚]
  F --> G[释放全局锁]
全局锁作用
flowchart LR
  A[全局锁] --> B[目的]
  B --> B1[防止一阶段提交后 二阶段提交前 其他事务修改同一行数据]
  A --> C[实现]
  C --> C1[基于行级锁]
  C --> C2[TC 记录 lock_record 表]
  A --> D[代价]
  D --> D1[全局锁存在期间 同一行不能有其他事务修改]
  D --> D2[影响并发性能]
  A --> E[关键区别]
  E --> E1[一阶段释放本地锁 但保留全局锁到二阶段结束]
AT vs 2PC vs TCC 对比
flowchart TB
  A[对比维度] --> A1[侵入性]
  A --> A2[一致性]
  A --> A3[阻塞]
  A --> A4[锁机制]
  A --> A5[回滚方式]
  A1 --> A1V[2PC 低 AT 低 TCC 高]
  A2 --> A2V[都是强一致]
  A3 --> A3V[2PC 会 AT 不阻塞 TCC 不阻塞]
  A4 --> A4V[2PC 行锁 AT 全局锁 TCC 业务锁]
  A5 --> A5V[2PC redo log AT undo_log TCC 业务代码]
知识关系

⬆️ 前置(Prerequisite)

distributed-tx-overview2pc-3pc

🔄 延伸(Extends)

cross-border-payment-design

⚡ 对比(Contrast)

TCC 模式— AT 低侵入框架自动回滚;TCC 高侵入业务显式补偿但锁粒度更细2PC— 2PC 全程持锁会阻塞;AT 一阶段释放本地锁但保留全局锁,不阻塞
🎯 概念 📏 规则 ⚠️ 误区 🔍 追问 ✨ 口诀 共 0 张卡,点击翻面