运维手动改了一行数据,Seata 回滚时把它覆盖了:AT 模式全局锁和 undo_log 的 3 个被忽略的边界
title: 运维手动改了一行数据Seata 回滚时把它覆盖了AT 模式全局锁和 undo_log 的 3 个被忽略的边界date: 2026-08-22category: 分布式事务tags: [Java, 后端, 分布式事务, Seata, 微服务]我们订单和库存两个服务用 Seata AT 模式做分布式事务。AT 模式最吸引人的点是「不用写回滚代码」——你只管写业务 SQLSeata 在背后帮你记 undo_log、自动回滚。但正是这种「无感」让我们在某次线上事故里栽了跟头一次全局事务回滚把我们运维同事手动改掉的一行价格数据给覆盖回滚前的值了。这篇把 AT 模式的全局锁、undo_log 插入时机和隔离边界讲清楚尤其说清楚「为什么它不能保护非 Seata 改的数据」。事故现场回滚把人工修正覆盖了那天的链路是用户下单 → 订单服务AT 事务扣库存 → 调用库存服务。库存服务这边的分支事务改了stock表Seata 记了 undo_log。过程中因为发现一个商品标价错了运维直接在 DB 里UPDATE stock SET price99 WHERE id1把价格从 199 改成 99。随后订单服务那边超时全局事务发起回滚。Seata 在库存服务这边执行 undo_log 回滚把stock表里 id1 的那行整个回滚到了事务开始前的值——也就是把运维刚改的 99 又改回了 199。人工修正丢了。根因一句话Seata AT 的 undo_log 回滚是「整行还原」它不知道中间还有人用手动 SQL 改过这行。AT 一阶段本地事务 undo_log 是原子的要理解覆盖是怎么发生的得先看 AT 一阶段干了什么。Seata 通过数据源代理在你的业务 SQL 执行前后各快照一次// 业务侧只写普通 MyBatis 代码代理在底层拦截 GlobalTransactional public void createOrder(long productId, int count) { // 1. 解析 SQL生成 before image执行前快照 // 2. 执行 UPDATE stock SET count count - ? WHERE id ? // 3. 生成 after image执行后快照 // 4. 把 before/after image 连同业务SQL写入 undo_log 表同一本地事务 stockMapper.deduct(productId, count); orderMapper.insert(...); }Seata 在ExecuteTemplate里做的事简化逻辑// AbstractDMLBaseExecutor 执行流程简化 public T execute(Object... args) { // 执行业务 SQL 前先查 before image TableRecords beforeImage beforeImage(); // 执行真正的 SQL T result statementCallback.execute(statement, args); // 执行后查 after image TableRecords afterImage afterImage(beforeImage); // 把前后镜像写进 undo_log和业务 SQL 在同一个本地事务里提交 undoLogManager.flushUndoLog(connection, beforeImage, afterImage, ...); return result; }逐行说三个关键点beforeImage是在你的 SQL 真正执行前查的代表「事务开始前这行长什么样」。afterImage是执行后查的代表「事务结束后这行长什么样」。undo_log 的写入和业务 SQL绑定在同一个本地事务里提交——要么都成要么都滚。这就是为什么 AT 模式「不用写回滚代码」回滚信息已经在库里了。undo_log 表长什么样为什么必须和业务同库很多人配 Seata 时把 undo_log 表建到了一个独立的库结果回滚时找不到日志。undo_log 的结构MySQL大概是这样CREATE TABLE undo_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, branch_id BIGINT NOT NULL, -- 分支事务 ID xid VARCHAR(100) NOT NULL, -- 全局事务 ID context VARCHAR(128), rollback_info LONGBLOB NOT NULL, -- 序列化后的 before/after image log_status INT, log_created DATETIME, log_modified DATETIME, UNIQUE KEY ux_undo_log (xid, branch_id) );rollback_info里存的是 before/after image 的序列化默认 Jackson。我们早期出过一次事故undo_log 表和业务表不在同一个数据源本地事务提交成功、但 undo_log 写入因为跨库分成了两个事务undo_log 没提交成功。后来全局事务要回滚TC 下发回滚指令分支去查 undo_log 却查不到事务直接悬挂数据停留在「扣了库存没建订单」的中间态只能人工修。所以这条要刻在脑子里undo_log 表必须和业务表在同一个库、同一个本地事务。回滚时用 before image 整行还原再加全局锁防冲突二阶段回滚时Seata 取出 undo_log 里的 before image生成反向 SQL 把数据还原// 回滚执行简化用 before image 拼出 UPDATE 还原 public void undo() { // 1. 校验 after image 和当前库里数据是否一致防止脏写 // 2. 加全局锁Global Lock阻止其他 Seata 事务并发改这行 // 3. 用 beforeImage 还原数据 // 4. 删除 undo_log UndoLogManager.undo(dataSourceProxy, ...); }这里有两个被忽略的边界全局锁只对「同样走 Seata」的事务生效。它防的是「两个 Seata 全局事务并发改同一行」时的脏写。而我们运维直接连 DB 改的那行根本不走 Seata全局锁管不到它。所以回滚时 Seata 以为「这行还是我事务结束时的样子」二话不说用 before image 还原把人工改动覆盖了。after image 一致性校验救不了这种场景。Seata 回滚前会比对「当前库里的数据」和 after image如果不一致就报错脏写保护。但运维改的是price字段而我们的回滚只还原了count字段所在的那次快照——具体覆盖哪些列取决于 undo_log 记录的是整行还是部分列。Seata 默认按「SQL 影响的主键行」整行还原所以 price 也被还原了。哪个环节出了问题说清楚责任边界这不能算 Seata 的 bug而是我们误用了它的隔离语义。AT 模式承诺的是「分布式事务之间的隔离」保证的是「多个 Seata 全局事务不会互相脏写」。它从设计上就不保护「外部绕过 Seata 直接改库」的数据——也不可能保护因为它根本不知道外部改过。我在团队里定的规矩后来有三条上了 Seata AT 的库禁止任何绕过框架的直接写运维改数要走同一套 Seata 应用或先暂停相关全局事务。undo_log 表必须和业务表在同一个数据源、同一个本地事务里——这条上面已经强调过是生死线。全局事务超时tx-service-group里的timeout默认 60 秒要根据实际链路设置。我们有一次分支事务上报慢超过了全局超时TC 已经判定回滚但分支还没提交完造成了「回滚指令和分支提交撞车」的脏数据最后只能人工修数。AT 的性能代价undo_log 的写放大与回滚成本AT 模式不是免费午餐它每笔写 SQL 都要额外做「前后镜像 写 undo_log」这是实打实的写放大。我们压测过同样一个扣库存的 UPDATE开 AT 比不开单 SQL 的 RT 多了约 1.5 毫秒主要是 undo_log 的 INSERT 和镜像查询。量小无所谓量大就明显。更隐蔽的是回滚成本AT 回滚是用 before image 反向 UPDATE如果回滚发生在热点行上会和业务写抢同一行锁放大锁竞争。-- 回滚时 Seata 实际执行的反向 SQL由 before image 拼出 UPDATE stock SET count 100, price 199 WHERE id 1; -- 同时删除 undo_log DELETE FROM undo_log WHERE xid ... AND branch_id ...;所以我的经验是AT 适合「写并不极端频繁、但要求事务简单」的中后台如果是「每秒几万次扣减」的热点账户AT 的镜像开销和回滚锁竞争会成为瓶颈那种场景不如上 TCC把「扣减 冻结」做成业务层的幂等操作绕开全局事务的镜像成本。压测数据给了我们直观结论同一个热点账户走 ATTPS 从 8000 掉到 1200同样逻辑走 TCC 手动冻结还能维持在 6000 以上。镜像开销和回滚锁竞争在高频写场景是真的贵不是理论上说说。和 TCC、Saga 的取舍模式侵入性隔离保证适合AT低加个注解只隔离 Seata 事务间大部分同库/同框架的写场景TCC高写三套接口业务层强一致资金、强一致Saga中写补偿最终一致长流程、跨系统我的判断AT 模式适合「内部服务都统一用 Seata」的中后台系统图它省事一旦你的数据会被外部系统、人工、或异构应用直接修改AT 的自动回滚就会变成隐患这种场景要么上 TCC 把控制力拿回来要么在数据入口统一收口。别因为「不用写回滚」就盲目上 AT我们那次覆盖事故省下的回滚代码最后用三倍的人工修数还了回去。复盘数字那次覆盖发生在周三 16:20 左右影响 1 个商品、1 行价格数据从发现到人工修复耗时约 50 分钟要先把全局事务相关链路熔断。事后我们给所有 Seata 库加了「直接写库」的审计告警违规写操作当天就拦下了 2 次。全局事务默认超时从 60 秒调到 120 秒后分支超时导致的回滚冲突从每周 1~2 次降到零。undo_log 表统一归并到业务库后回滚失败率从 0.4% 降到了零。思考题AT 模式用 before image 整行还原意味着它其实会「顺手还原」掉事务期间别人改过的其他列。如果你的业务要求「只回滚事务自己改的列、保留别人改的列」AT 模式还能用吗你会怎么改

相关新闻

看门狗每 10 秒续一次期,业务却跑了 40 秒:Redisson 锁续期源码里藏着的 2 个默认陷阱

看门狗每 10 秒续一次期,业务却跑了 40 秒:Redisson 锁续期源码里藏着的 2 个默认陷阱

title: 看门狗每 10 秒续一次期,业务却跑了 40 秒:Redisson 锁续期源码里藏着的 2 个默认陷阱 date: 2026-08-22 category: 分布式锁 tags: [Java, 后端, Redis, Redisson, 并发编程]我们订单服务用 Redisson 做分布式锁,锁一段「扣减库存 生…

2026/8/22 16:15:32 阅读更多 →
设计模式结构型——桥接模式

设计模式结构型——桥接模式

目录 什么是桥接模式 桥接模式的实现 桥接模式角色 桥接模式类图 桥接模式举例 桥接模式代码实现 桥接模式的特点 优点 缺点 使用场景 注意事项 什么是桥接模式 桥接(Bridge)模式是用于把抽象化与实现化解耦,使得二者可以独立变化…

2026/8/22 16:14:32 阅读更多 →
KMS_VL_ALL_AIO 本地KMS快速激活指南:从零到一,一个批处理搞定 Windows 和 Office 激活

KMS_VL_ALL_AIO 本地KMS快速激活指南:从零到一,一个批处理搞定 Windows 和 Office 激活

KMS_VL_ALL_AIO 本地KMS快速激活指南:从零到一,一个批处理搞定 Windows 和 Office 激活 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 重装系统后"未激活"的水…

2026/8/22 16:14:32 阅读更多 →

最新新闻

农业边缘视觉识别:轻量模型+物理先验的实战落地

农业边缘视觉识别:轻量模型+物理先验的实战落地

1. 这道赛题到底在考什么:剥离竞赛外壳,看清图像识别的真实战场“亚太数学建模竞赛A题:水果采摘机器人的图像识别技术”——光看标题,很多人第一反应是“不就是用YOLO跑个检测框?再加个分类模型分个苹果香蕉&#xff1…

2026/8/22 19:40:49 阅读更多 →
快手AI Agent开发面试核心要点与实战技巧

快手AI Agent开发面试核心要点与实战技巧

1. 快手AI Agent开发面试核心要点解析最近在准备快手AI Agent开发岗位的面试,发现这个方向涉及的知识点既深且广。作为国内领先的短视频平台,快手在AI Agent领域的布局相当前沿,面试考察点也很有代表性。结合我自己的准备过程和实际面试经验&…

2026/8/22 19:40:49 阅读更多 →
数学建模中的拟合原理、代码实现与结果诊断

数学建模中的拟合原理、代码实现与结果诊断

1. 什么是拟合?它在数学建模里到底解决什么问题?“数学建模之拟合及其代码”——这标题看着平实,但背后藏着建模实战中最常卡壳、最易被低估的核心环节。我带过七届校队,审过三百多份国赛/亚太杯初稿,发现一个惊人规律…

2026/8/22 19:40:49 阅读更多 →
TeamFusion:构建具备开放式协作能力的多智能体系统

TeamFusion:构建具备开放式协作能力的多智能体系统

1. 项目概述:当AI学会“组队打怪”最近在捣鼓多智能体系统(Multi-Agent Systems, MAS)时,我一直在琢磨一个事儿:现在的AI智能体,单个拎出来能力都挺强,能写代码、能分析数据、能画画&#xff0c…

2026/8/22 19:40:49 阅读更多 →
RedisDesktopManager 连不上、变卡?3 条命令定位故障,3 个参数提速

RedisDesktopManager 连不上、变卡?3 条命令定位故障,3 个参数提速

RedisDesktopManager 连不上、变卡?3 条命令定位故障,3 个参数提速 【免费下载链接】RedisDesktopManager RedisInsight/RedisDesktopManager: RedisDesktopManager 是一个用于 Redis 数据库管理的桌面应用程序,可以用于连接和操作 Redis 数据…

2026/8/22 19:40:49 阅读更多 →
智慧教育实习系统:SpringBoot+Vue3全栈开发实践

智慧教育实习系统:SpringBoot+Vue3全栈开发实践

1. 项目概述与核心价值2025年智慧教育实习实践系统是一个典型的"前后端分离微服务"架构的现代教育管理平台。这个系统最核心的价值在于解决了传统教育实习管理中的三大痛点:流程碎片化:实习申请、审批、报告提交等环节通常分散在不同平台&…

2026/8/22 19:39:49 阅读更多 →

日新闻

沉金PCB工艺实战指南:从设计到SMT焊接的可靠性保障

沉金PCB工艺实战指南:从设计到SMT焊接的可靠性保障

在电子硬件开发领域,PCB(印制电路板)的沉金工艺是提升产品可靠性和焊接质量的关键环节。对于需要高密度互连、长期稳定运行或高频信号传输的板卡,如“黍姐仿通行证”这类可能涉及身份识别、数据交互的硬件项目,选择正确…

2026/8/22 0:00:11 阅读更多 →
电气考研电路八月强化四步法:从知识体系到真题实战的闭环攻略

电气考研电路八月强化四步法:从知识体系到真题实战的闭环攻略

这次我们来看一个针对电气考研电路科目的学习规划项目。它不是软件工具,而是一套聚焦于8月份关键节点的备考策略。对于电气工程考研的同学来说,电路分析是专业课的重中之重,也是拉开分差的关键。进入8月,复习进入强化阶段&#xf…

2026/8/22 0:00:11 阅读更多 →
消除AI代码的“AI味”:Claude Code设计优化技能配置与实战指南

消除AI代码的“AI味”:Claude Code设计优化技能配置与实战指南

大家好,我是专注于前端开发与AI工具实践的技术博主。在日常使用 Claude Code 等AI编程助手时,你是否也遇到过这样的困扰:生成的代码功能上没问题,但代码风格、组件设计、交互逻辑总透着一股“AI味”——布局单调、样式简陋、交互生…

2026/8/22 0:00:11 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/21 3:21:33 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/22 8:09:09 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/21 6:07:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/22 18:08:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/22 7:31:03 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →