连载中 12/18

Seata AT 原理:undo_log 与全局锁

2026-06-20 · 6187 阅读 · 0 评论 · 0 赞

零侵入的魔法从哪来

AT 模式最迷惑人的地方:业务代码一行不改,回滚全自动——补偿逻辑从哪冒出来的?答案藏在代理数据源里:Seata 把你的 DataSource 包了一层,所有 SQL 先经过它。它做的事一句话概括:执行前拍张照(前镜像)、执行后拍张照(后镜像)、把两张照片存进 undo_log 表。回滚就是看照片逆操作。拆开一阶段二阶段细看。

一阶段:本地事务提前提交

拦截 SQL: update account set balance=90 where id=1
1 查前镜像:  select balance from account where id=1  → 100
2 执行 SQL:  balance 100 → 90
3 查后镜像:  select balance from account where id=1  → 90
4 组装 undo_log(前后镜像 + SQL 信息)写入本库
5 本地事务提交:业务 SQL + undo_log 原子落库
6 向 TC 注册分支并汇报状态

注意第 5 步——一阶段结束时,本地事务已经提交了,数据库行锁释放了。这是 AT 与 2PC 的根本区别:2PC 在 prepare 后锁着资源等全局指令;AT 把「等」的时间压缩到了极限,各分支的本地事务自顾自提交,全局的成与败交给二阶段处理。这就是 AT 吞吐高的根源。

二阶段:提交很快,回滚要验

全局提交:数据已经落库,什么都不用做,TC 通知各分支异步批量删除 undo_log 即可——提交路径近乎零成本。

全局回滚:RM 收到回滚通知后分两步走:先校验——把 undo_log 里的后镜像和当前表数据比对,一致说明这一行没人动过,安全;再回滚——根据前镜像自动生成反向 SQL(update 回原来的值、delete 掉 insert 的行)执行,最后删 undo_log。若比对不一致,说明有别人在全局事务外改了这行——脏写发生,反向 SQL 会覆盖别人的修改,Seata 拒绝执行并告警转人工。防脏写是 AT 的生命线。

全局锁:写在 TC 上的轻量锁

一阶段就提交了本地事务,两个全局事务并发改同一行怎么办?A 事务改了 balance 还没走到二阶段,B 事务也来改——A 回滚时发现数据被 B 改了,脏写。Seata 的答案是全局锁:分支事务在提交本地事务之前,必须先去 TC 拿到这行的全局锁(表名 + 主键维度);拿不到就自旋重试,超时则一阶段整体回滚。全局锁管住「全局事务之间」的写冲突,数据库行锁管住「本地并发」,两层各司其职。

锁从数据库行锁挪到 TC 内存,持有时长从「整个事务」缩短为「一阶段的瞬间」——这是 AT 快的另一半原因。但反过来看,锁压到 TC 也意味着热点行是 AT 的天敌:一万笔事务同时抢某账户这一行的全局锁,自旋重试会把吞吐打穿,这正是下一篇的主题。

隔离性的诚实交底

AT 的隔离级别要交底清楚:写隔离靠全局锁保证读隔离默认没有——一阶段本地事务已提交,别的事务立刻能读到「全局上还没决定」的数据,相当于全局读未提交。Seata 提供加 @GlobalLock 或 select for update 的全局读方案,但都会拉低性能。所以业务设计要接受「中间态可见」,或者把强读一致的部分拆回本地事务——这与第 2 篇 BASE 的精神一脉相承。

维度AT 表现
业务侵入零(数据源代理 + 注解)
补偿方式前后镜像自动生成反向 SQL
一致性最终一致,默认读未提交
额外要求每个业务库建 undo_log 表,只支持关系库
软肋热点行全局锁竞争、脏写只能人工

小结

AT 一句话:代理数据源记前后镜像,一阶段本地事务提前提交换吞吐,二阶段按镜像反向回滚;全局锁压在 TC 防脏写,读未提交是默认,热点行是软肋。原理懂了,下一个问题接踵而至:账户余额这种天然的行热点,AT 抢锁抢到怀疑人生,TCC 冻结字段才是出路——下一篇:热点账户的锁冲突突围。

503

10 年全栈工程师 · 503咖啡馆主理人

#分布式事务#Seata#AT模式#undo_log#全局锁

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 3 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞