← 返回题目列表

Seata 的 AT 模式原理是什么?为什么能自动回滚?

高频 困难 第 15 / 27 题 更新于 2026/07/28
SeataAT模式分布式事务全局锁

简化版

Seata AT 模式是对业务无侵入的自动补偿型分布式事务。它靠代理数据源,在你执行 SQL 时自动记录数据修改前后的镜像(undo log),一阶段就直接提交本地事务(释放数据库锁),二阶段若全局事务成功则异步删掉 undo log,失败则用 undo log 里的「前镜像」自动生成反向 SQL 把数据改回去。它相当于「自动版的 TCC/Saga」,你只管写业务 SQL 加个 @GlobalTransactional 注解,回滚由框架自动做。

详细版

三个角色

  • TC(Transaction Coordinator,事务协调器):独立部署的 Seata Server,维护全局事务状态、协调提交/回滚。
  • TM(Transaction Manager,事务管理器):发起全局事务的一方(加了 @GlobalTransactional 的方法),决定全局提交还是回滚。
  • RM(Resource Manager,资源管理器):管理各分支事务(每个参与的数据库),负责注册分支、上报状态、执行提交/回滚。

两阶段流程

  • 一阶段:RM 拦截业务 SQL,解析它 → 查询前镜像(改之前的数据)→ 执行业务 SQL → 查询后镜像(改之后的数据)→ 把前后镜像存进 undo_log 表 → 提交本地事务(业务数据和 undo log 一起提交,本地锁马上释放)→ 向 TC 注册分支并申请全局锁。
  • 二阶段
    • 全局提交:TC 通知各 RM,异步删除 undo log 即可(数据已经在一阶段提交了)。
    • 全局回滚:TC 通知各 RM,RM 用 undo log 的前镜像生成反向 SQL,把数据恢复原样,再删 undo log。

关键机制

  • undo log:记录数据变更前后的快照,是自动回滚的依据。
  • 全局锁:Seata 自己维护的行级锁,防止两个全局事务同时改同一行导致回滚时数据错乱(保证写隔离)。

完整版教学

一、AT 模式解决什么:既要自动、又要高性能

2PC/XA 对业务无侵入但锁数据库太久(性能差);TCC 性能好但要写三个方法(侵入大)。AT 模式想两全:像 XA 一样对业务透明(只加注解、写普通 SQL),又像 TCC 一样不长时间锁数据库。它的做法是——一阶段直接提交本地事务(马上释放 DB 锁,这是性能关键),把「怎么回滚」的信息(undo log)提前记下来,需要回滚时再用它反向操作。

二、undo log:自动回滚的核心

AT 最巧妙的地方是自动生成回滚。它通过数据源代理拦截你的 SQL,在执行前后各查一次数据:

  • 前镜像(before image):SQL 执行前,这些行长什么样。
  • 后镜像(after image):SQL 执行后,这些行长什么样。

这两份快照连同 SQL 信息存进 undo_log 表,和业务数据在同一个本地事务里提交。回滚时,框架拿前镜像生成一条把数据改回去的反向 SQL(比如 update 后镜像 → 前镜像)。所以你不用写任何补偿代码,框架靠镜像自动”倒带”。删 undo log 也是在同事务或异步进行。

记忆点:AT = 一阶段直接提交 + 存前后镜像;回滚时拿前镜像自动生成反向 SQL 倒带。「自动补偿」的自动,就来自 undo log 镜像。

三、全局锁:解决 AT 的隔离性问题

因为一阶段就提交了本地事务、释放了数据库锁,如果不加控制,另一个全局事务可能在这期间也改了同一行并提交,那么第一个事务回滚时用「前镜像」倒带就会覆盖掉第二个事务的修改(脏写、更新丢失)。Seata 用全局锁解决:一阶段提交前,RM 要向 TC 申请这些行的全局锁,拿到才提交;别的全局事务想改同一行必须先拿全局锁,拿不到就等待/回滚。这保证了全局事务之间对同一行的写隔离

注意:全局锁只锁「参与全局事务的写」。默认隔离级别是读未提交(别的普通查询能读到中间态),如需读隔离要用 SELECT ... FOR UPDATE(会走全局锁校验)。

四、脏写与「回滚失败」的兜底

极端情况:如果有人绕过 Seata 直接改了数据(没走全局锁),回滚时框架会对比「当前数据」和「后镜像」——如果不一致,说明数据被别人动过,此时无法安全倒带,Seata 会报错并挂起,转人工处理,避免错误覆盖。这也是为什么用 AT 模式时,所有对相关表的写都应经过 Seata。

五、AT vs TCC vs XA(Seata 四模式里的三个)

维度XA 模式AT 模式TCC 模式
侵入无(加注解)大(三个方法)
DB 锁,全程一阶段就释放 DB 锁,用全局锁业务预留
回滚DB 原生undo log 自动反向手写 Cancel
依赖DB 支持 XA需 undo_log 表纯业务
性能较好
适用强一致低并发通用、无侵入首选资金/资源强约束

AT 是 Seata 最常用的默认模式,兼顾无侵入和性能,适合大多数业务;对隔离性要求极高或资金核心用 TCC。

六、常见误区与追问

这道题不能只背概念,要把「Seata AT 模式」放回真实分布式系统里解释:谁发起、谁协调、状态如何变化、失败后怎么兜底,以及它和性能、可用性、一致性的取舍。

回答层次要讲清的内容容易漏掉的边界
核心结论Seata AT 通过全局锁和 undo_log 在本地事务基础上自动生成回滚日志,实现非侵入式最终一致不要停在名词解释
流程机制TC 开启全局事务 -> RM 执行本地 SQL 并记录 undo_log -> 提交本地事务并释放本地锁 -> 全局提交删除 undo_log -> 全局回滚用 undo_log 补偿说明触发方、参与方、状态变化和兜底
工程取舍更新库存前记录 before image 和 after image,异常时用 undo_log 反向恢复分布式事务没有免费强一致,性能、可用性和业务侵入一定要取舍
Seata AT 模式 面试拆解:
1. TC 开启全局事务
2. RM 执行本地 SQL 并记录 undo_log
3. 提交本地事务并释放本地锁
4. 全局提交删除 undo_log
5. 全局回滚用 undo_log 补偿

记忆钩子:先说本地事务失效的原因,再拆协调、补偿、消息、幂等、对账和回滚边界;回答时要紧扣「Seata AT 模式」这道题,不要把相邻概念混成一段泛泛的分布式套话。

  • 误区:AT 模式等于 XA 强一致。 AT 一阶段本地提交,二阶段靠 undo_log 补偿,属于最终一致思路。
  • 误区:AT 对业务完全无要求。 需要表有主键、SQL 可解析,并注意脏写和全局锁冲突。
  • 误区:undo_log 可以随便删。 未完成全局事务依赖 undo_log 回滚,清理必须按状态安全执行。
  • 追问:全局锁解决什么? 防止其他事务修改已被全局事务占用的数据,避免回滚时数据被污染。
  • 追问:AT 优势是什么? 业务侵入低,适合关系型数据库常规 SQL 场景。
  • 追问:AT 不适合什么? 复杂 SQL、非关系型资源、长事务和高冲突热点更新。

七、加强记忆

Seata AT 模式 = 无侵入自动补偿事务,靠 TC/TM/RM 三角色协作。一阶段拦截 SQL、存前后镜像到 undo_log、直接提交本地事务并释放 DB 锁、注册分支申请全局锁;二阶段全局提交就异步删 undo log,全局回滚就用 undo log 的前镜像自动生成反向 SQL 倒带。核心是 undo log 实现自动回滚、全局锁保证全局事务间写隔离。你只需 @GlobalTransactional + 普通 SQL,兼顾无侵入与高性能,是 Seata 默认首选模式。