
简介《Archery使用手册》定位于 SQL 审核查询与 MySQL 运维场景面向开发人员、测试人员和 DBA帮助读者熟悉 Archery 的功能组成、审核流程与日常实例管理方法。压缩包内为 1 个 doc 文档大小约 1.2MB内容围绕 SQL 审核规则、SQL 优化建议、实例管理和工具插件展开并配有开发环境、测试环境的工单审核示例以及回滚 SQL、慢日志分析、会话终止、事务与锁排查、账号授权、动态参数配置等实践说明。文档还介绍了 PTArchiver 数据归档、Binlog2SQL 解析与回滚、SchemaSync 结构同步等插件的适用场景便于按模块查阅并对照完成审核、优化与故障排查任务。手册按功能说明、操作流程和案例实践组织适合需要规范 SQL 上线、降低高危操作风险、提升实例巡检效率的团队参考。已有 1478 人学习可作为 Archery 入门培训、平台功能梳理和日常运维查阅的参考手册。1. SQL 检测一片红、工单提交不上去Archery 上手第一道坎先说最典型的现场SQL 文件粘进 Archery 工单页点「SQL 检测」红字一片提交按钮点不动或者检测过了工单提交出去卡在「待审核」一整天再或者审核通过、点「立即执行」工单直接报执行失败。这三种几乎是这类 SQL 审核查询平台最高频的求助新手第一反应是平台坏了熟手知道八成是审核规则、流程配置或实例状态里某一个小项没对上。下面按「报错 → 根因 → 怎么改」的顺序拆开写适合提交工单被卡住的研发、负责审核的项目经理、刚接手实例管理的 DBA照着页面路径和命令走一遍多数问题当场能定位。2. SQL 检测报 error 提交不了先分清是语法错还是规范错Archery 的 SQL 检测不是连库执行一遍看结果而是先把 SQL 做语法解析再拿解析出来的结构去套一套自定义审核规则。这个设计决定了它报 error 的原因只有两大类一类是解析器根本读不懂你的语句另一类读懂了但不合规范。两类错误的改法完全不一样混在一起看提示就会来回改、来回错。我在排查时习惯先把工单里那条提示原文读三遍看它说的是「syntax」还是「rule」。前者去改语句结构后者去补表设计或拆分操作方向错了改十遍都是红。2.1 语法解析失败括号、关键字和版本方言解析器读不懂的典型表现是提示里带 parse、syntax、unexpected token 之类的词而且往往整条 SQL 全红不是某一行红。常见诱因有三类括号或引号没闭合用了保留字做表名或列名却没加反引号用了当前实例版本不支持的写法。-- 反面示例order 是保留字未加反引号括号不配对 CREATE TABLE demo.order ( id INT NOT NULL, amount DECIMAL(10,2) PRIMARY KEY (id) );这段在解析阶段就会挂掉原因不是缺注释而是order撞了保留字、amount行尾漏了逗号。修正后应该是-- 正面示例保留字加反引号逗号补齐注释齐全 CREATE TABLE demo.order ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主键, amount DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 金额, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单表;这里的逻辑说明反引号解决保留字冲突AUTO_INCREMENT配合BIGINT UNSIGNED是自增主键的稳妥写法COMMENT不只是给人看的很多团队的审核规则要求表注释和列注释必填缺了就判 error。参数上要注意DEFAULT CHARSET必须和实例的默认字符集一致跨字符集的建表语句即使语法通过执行阶段也可能因为校对规则冲突失败。还有一种容易被忽略的情况从别的数据库导出的 SQL 带着方言语法的痕迹比如IF NOT EXISTS加在某些位置、函数名大小写敏感、反斜杠转义差异。这类问题不用猜把语句拆成最小片段逐条检测哪一条开始红就是那一条的问题。2.2 规范命中的 error主键、注释、字段类型语法通过但规则不通过时提示通常是中文业务语言比如「建表语句必须包含主键」「表和列必须有注释」「不建议使用 TEXT 类型」。这类错误的根因不在语句写法而在表设计没有满足团队规范而规范是可以在后台配的。我一般会做三步第一看提示里点名的规则是哪一条第二确认这条规则是不是团队真的要求如果是历史遗留的过严规则找管理员调整第三如果是自己漏了按规则补齐再提交。补齐的动作基本就是加主键、加注释、把大字段换成合适类型、给时间字段加默认值。-- 规范不通过的典型写法 CREATE TABLE demo.log_flow ( id INT NOT NULL, content TEXT, created_at DATETIME ) COMMENT日志流水; -- 按规范补齐 CREATE TABLE demo.log_flow ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主键, content VARCHAR(2000) NOT NULL DEFAULT COMMENT 内容, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_created_at (created_at) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT日志流水表;参数说明created_at加了默认值避免插入时该列为 NULL 触发严格模式报错idx_created_at是为后续按时间清理或归档准备的索引缺了它归档任务会全表扫TEXT改VARCHAR(2000)是为了配合规范里对大字段的限制。注意VARCHAR长度不是越大越好超过 255 在部分字符集下会额外占长度字节按业务真实上限给。2.3 高危语句被自动驳回不是报错是策略拦截有一类「提交不上去」根本不显示 error而是工单提交后状态直接变成已驳回或者检测阶段提示「高危语句不允许提交」。根因是平台对无条件 UPDATE、无条件 DELETE、DROP、TRUNCATE 这类语句做了自动拦截这是审核平台的价值所在不是 bug。遇到这种情况不要想办法绕过常见做法是把大操作拆小-- 被拦截的无条件更新 UPDATE demo.order_flow SET status 0; -- 改成带条件 分批 UPDATE demo.order_flow SET status 0 WHERE id 0 AND status 9 LIMIT 1000;逻辑说明WHERE是让语句从全表更新变成范围更新的关键LIMIT 1000控制单次影响行数避免长事务和主从延迟。实际执行时用脚本循环跑每批之间 sleep 几十毫秒直到影响行数为 0 为止。参数上要注意LIMIT必须配合有序的WHERE条件通常按主键区间推进否则每次扫的范围重叠效率反而更差。如果确实是合理的全表操作比如上线时初始化一张新表的字段就走管理员通道让有权限的人在实例管理里直接执行或者临时放宽规则后立刻恢复。我见过最折腾的一次是有同学为了绕过高危拦截把 UPDATE 拆成 2000 条单行语句提交审核页直接卡死最后还得手工清工单。2.4 工单提交成功却推不动审核人和通知的两处坑检测全绿、提交成功工单停在「待审核」一天没人处理这属于流程问题不是 SQL 问题。Archery 的流程是按角色配的开发环境常见链路是研发工程师提交、项目经理审核测试环境是测试同事发起并自行审核执行。定位顺序先看工单详情里当前节点挂在谁身上再让对应的人登录平台点右上角的通知按钮看待办最后才怀疑通知渠道。这里有两个高频坑一是流程里配的审核人已经换岗或离职工单永远挂在他名下二是钉钉通知发出去了但接收人没绑对人以为没收到。提示工单提交后不要重复提交第二遍重复工单会在执行阶段互相抢锁反而制造出莫名其妙的执行失败。排查通知问题时我会先确认平台侧有没有发出记录再去接收端确认机器人或应用是否还在群里。如果平台侧没有记录多半是通知配置里的接收人或渠道被改过如果平台侧有记录但人没看到就是接收端的事跟 SQL 本身无关别在 SQL 上继续折腾。3. 工单执行失败与回滚 SQL 取不到DDL 和 DML 的边界必须认清检测通过只代表语句能解析、符合规范不代表目标实例上一定能执行成功。执行阶段是把语句真正发到 MySQL这时候才暴露环境差异、权限、锁冲突。而回滚语句能不能生成取决于操作类型和 binlog 配置这两件事经常被混为一谈导致出事时才发现「回滚按钮点开是空的」。3.1 立即执行报失败五个高频根因逐个排点「立即执行」后工单变红错误信息通常来自 MySQL 本身比如表不存在、字段不存在、Duplicate key、Lock wait timeout、Access denied。我把它们归成五类第一类是环境不一致。检测阶段不连库所以表名写错、字段名拼错、库名大小写差异检测都能过执行才报错。第二类是结构冲突目标表已经有同名字段或同名的索引。第三类是权限不足执行账号只有 DML 权限工单里却有 ALTER。第四类是锁等待超时目标表正被长事务占着。第五类是数据本身冲突比如给已有重复值的列加唯一索引。定位时先把工单里的错误原文抄出来然后到 Archery 的 SQL 查询功能里在同一个实例上手工执行验证-- 确认表结构和字段是否存在、类型是否与工单一致 SHOW CREATE TABLE demo.order_flow; -- 确认执行账号的实际权限别只看账号管理页面的展示 SHOW GRANTS FOR app_user%; -- 确认是否有长事务占着这张表 SELECT trx_mysql_thread_id, trx_started, trx_query FROM information_schema.innodb_trx ORDER BY trx_started;逻辑说明SHOW CREATE TABLE是排环境不一致最快的命令一次就能看出字段名、类型、字符集和索引的真实状态SHOW GRANTS要看的是实际生效的授权账号管理页面授权成功不等于 MySQL 侧已经生效innodb_trx用来确认是不是被别的事务堵住了。参数上注意app_user%的 host 部分必须和账号实际定义完全一致%和具体网段是两个不同的账号。3.2 定时执行到点没动静调度、时区和排队选了「定时执行」之后时间到了却没执行工单状态还停在待执行根因通常是三类调度组件没在跑、时间按 UTC 存但按本地时间理解、同一实例上排了多个工单在串行等。第一类最好确认找管理员看调度任务是否存活平台侧一般有执行记录记录为空就是没触发。第二类很隐蔽页面上填 22:00实际在北京时间凌晨才跑查执行记录的时间戳能对出来。第三类是设计如此同一实例的工单通常串行执行前一个卡住后面全等着去看前一个工单卡在哪。我一般的做法是重要变更不用定时改成当场执行并盯着必须定时的把时间提前半小时并且提前十分钟确认前序工单已经结束。这个习惯救过我一次某次促销前夜的变更因为前一个工单卡在锁等待上定时没触发幸好提前看了。3.3 回滚 SQL 是空的DDL 不可回滚DML 依赖 binlog这是最容易翻车的地方。点「下载回滚 SQL」或「查看回滚 SQL」拿到空内容绝大多数情况不是平台出错而是两种必然结果之一。第一种你执行的是 DDL。建表、加字段、改字段类型、加索引这些操作在 binlog 里记录的是语句本身而不是行变更平台没法反向推算出一条安全的回滚语句所以 DDL 天然不可回滚。这也是为什么很多团队要求 DDL 变更必须写清楚逆向操作比如加字段的回滚是删字段但要先确认字段里没有还在用的数据。第二种你执行的是 DML但实例 binlog 配置不满足要求。行级回滚需要 binlog 是 ROW 格式并且记录完整的行镜像否则只能拿到变更前后的部分列生成不出可用的反向语句。-- 上线前先确认这三项别等出事才发现回滚语句是空的 SHOW VARIABLES LIKE log_bin; -- 必须是 ON SHOW VARIABLES LIKE binlog_format; -- 必须是 ROW SHOW VARIABLES LIKE binlog_row_image; -- 必须是 FULL参数说明log_bin为 OFF 时根本没有 binlog 可用binlog_format为 STATEMENT 或 MIXED 时平台拿到的不是行变更回滚语句生成会失败或不准binlog_row_image为 MINIMAL 时只记录被改的列回滚语句会缺列执行会报错。这三项里任何一项不对正确做法是先改配置再上线而不是先上线再祈祷。注意binlog 有保留期限过了保留期文件会被清理回滚语句也会跟着失效。数据要恢复的话越早动手成功率越高。3.4 用 binlog2sql 兜底按位点把变更捞出来平台侧的回滚语句拿不到或者工单记录已经被清理就得手工从 binlog 里解析。Archery 的工具插件里把 binlog2sql 做了可视化选实例、选 binlog 文件、填起止位点就能拿到原始 SQL 或者回滚 SQL。命令行方式更适合排查因为可以先用mysqlbinlog确认位点里到底有什么# 先看位点区间内的原始事件确认这段 binlog 里确实是目标表的变更 mysqlbinlog --start-position857 --stop-position1183 -vv master-bin.000009 | head -60 # 确认无误后用 binlog2sql 生成回滚语句-B 表示 flashback python binlog2sql.py -h127.0.0.1 -P3306 -uuser -ppassword \ -d demo -t order_flow \ --start-filemaster-bin.000009 --start-pos857 --stop-pos1183 \ -B rollback.sql逻辑说明--start-pos和--stop-pos是精确到字节的位点必须和--start-file配对使用-d和-t限定库表不加会把同区间内其他表的变更一起解析出来-B输出反向语句去掉-B就是原始语句-vv让mysqlbinlog输出可读的行变更方便先验证。参数上最容易错的是位点很多人从平台页面上看到的是起始位点却忘了填结束位点结果把整段 binlog 全解析了回滚脚本里混进其他业务表的语句直接执行就是灾难。我的做法是先把解析结果head出来看前 20 行确认库表名、字段、时间都对再决定要不要执行。另外重申一次边界binlog2sql 只能回滚 DMLDDL 操作解析出来也没法反向执行。所以改表结构之前先想清楚万一改错了怎么手工退回去把逆向语句写进变更单这比事后找 binlog 靠谱得多。4. 数据库被阻塞杀不掉进程、事务、锁三处对着看业务报警说接口超时登录数据库一看一片 S 锁等待想杀会话又不知道杀哪个这是最典型的线上故障现场。Archery 的会话管理把进程状态、事务信息、锁信息分成了三个页面很多人只用了第一个结果要么看不到完整 SQL要么杀错连接要么杀完立刻又回来。4.1 进程状态看不到完整的 SQL两个开关没打开点进会话管理右上角先选数据库实例再选 command 类型默认是 query只能看到正在查询的连接。如果想看全部连接包括 Sleep 状态的必须切成 All否则那些挂着不动的连接完全隐身而它们往往就是持锁不放的元凶。第二个坑是 SQL 显示不全。页面默认截断长语句必须先勾选「完整 INFO」才能看到完整的 SQL 文本。我见过不少人对着截断的UPDATE demo.order_flow SET ...猜了半天勾上之后才发现 WHERE 条件里少了一个索引列。正确顺序是选实例 → command 选 All → 勾选完整 INFO → 按 time 倒序排 → 找执行时间最长的那个连接。这一步做完阻塞现场基本就清楚一半了。4.2 事务信息和线程 ID 怎么对照进程状态看到的是连接事务信息看到的是事务两者靠线程 ID 关联。事务信息页里的trx_mysql_thread_id就是进程状态页里的 THREAD ID这个对应关系是排查的核心。-- 手工核对事务、线程、状态三者对照 SELECT trx_mysql_thread_id AS thread_id, -- 对应 Archery 进程状态页的 THREAD ID trx_state, -- RUNNING 表示还在跑LOCK WAIT 表示在等锁 trx_started, -- 事务开始时间越早越可疑 trx_rows_locked, -- 持锁行数大数字说明影响面广 trx_query -- 当前语句长事务里可能为 NULL FROM information_schema.innodb_trx ORDER BY trx_started;参数说明trx_state为LOCK WAIT的基本可以确定是受害者而不是元凶真正要处理的是它等待的那个事务trx_started用来判断事务存活时长超过几十秒的写事务在业务库里都算异常trx_query为空不代表事务空闲可能是事务已经执行完语句但没提交这种「开了事务忘提交」的情况最坑。要终止某个事务正确路径是拿trx_mysql_thread_id回到进程状态页搜索这个线程 ID选中后点「终止会话」。不要凭 SQL 文本去猜连接两条一样的 SQL 可能来自不同连接杀错了业务直接报连接断开。4.3 锁信息从等待方找到阻塞方锁信息页展示的是当前的锁等待关系。核心读法是等待事务的 SQL 就是被阻塞住的那条语句页面同时会给出阻塞方的线程 ID。拿到这个 ID回到进程状态页搜索、终止链路就通了。这个场景可以自己复现一遍理解了复现过程线上就不会慌。开两个会话第一个会话显式开事务并更新一行但不提交-- 会话 A开启事务更新 id2 的行故意不提交 BEGIN; UPDATE demo.t2 SET ename blocker WHERE id 2; -- 此处保持事务不提交第二个会话执行同样的更新会一直转圈-- 会话 B同一行被会话 A 的行锁挡住 UPDATE demo.t2 SET ename victim WHERE id 2;此时锁信息页里会话 B 的语句显示为等待事务的 SQL阻塞方线程 ID 指向会话 A。参数上要注意只有两个会话操作同一行、且都走主键或唯一索引时才会出现这种干净的行锁等待如果 WHERE 条件没有索引会升级成锁大量行甚至锁全表这时候锁信息页会看到成片的等待处理优先级要立刻提高。4.4 杀完立刻回来、杀了没反应两种常见误判第一种终止会话后几秒钟同一个 SQL 又出现了。根因不是没杀掉而是应用侧连接池检测到连接断开后自动重连并重试业务逻辑没变SQL 就还会再来一遍。这时候继续杀只是和连接池对赌正确做法是先停掉对应的定时任务或开关或者临时在数据库侧限制再从业务侧修 SQL。第二种点了终止会话没反应进程还在。常见原因有三个执行终止的账号没有 PROCESS 或 SUPER 权限被杀的是一个大事务MySQL 正在回滚进程状态显示Rolling back这时候只能等强行再杀也快不了杀的是KILL QUERY而不是KILL CONNECTION语句停了但连接还在事务可能还持着锁。-- 先看清状态再决定怎么杀 SHOW FULL PROCESSLIST; -- 只终止当前语句连接保留事务可能仍然持有锁 KILL QUERY 12345; -- 终止整个连接未提交事务会被回滚 KILL CONNECTION 12345;参数说明12345是进程状态里的 THREAD ID不是事务 IDKILL QUERY适合误执行的慢查询代价小但不清锁KILL CONNECTION才会触发事务回滚代价大但能真正释放锁。选择哪一个取决于你要解决的是「语句太慢」还是「锁不释放」这两件事经常被混着处理。5. 实例管理与工具插件的避坑清单五个真踩过的坑这一节记录的是我在实例运维和插件使用上真实翻过的车每条都按「现象 → 原因 → 解决」写能对上号就直接抄处理方式。5.1 清理 binlog 释放了磁盘从库同步断了现象主库磁盘告警在实例列表里选中某个 binlog 清理空间立刻回来了几分钟后从库报错复制中断。原因清理逻辑是把选中文件之前的 binlog 全部删掉如果从库还没消费到那个位点删除就等于抽掉了它要读的文件。这个操作没有「只删这一个」的选项选中即连带。解决清理前先在从库上确认已经应用到哪个文件、哪个位点只清理位点之前的文件。-- 在从库执行确认已读取和已执行到的位点 SHOW REPLICA STATUS\G -- 关注 Master_Log_File / Read_Master_Log_Pos 两个字段参数说明Master_Log_File是从库当前正在读的文件名要清理的文件必须严格小于它Read_Master_Log_Pos是文件内的位点两者结合才能判断安全边界。如果复制已经断了就得用备份加 binlog 重做代价远大于提前多看一眼。我后来的习惯是主库磁盘紧张先看能不能扩盘或者缩短保留天数清理 binlog 永远放在最后一步。5.2 pt-archiver 归档把线上拖慢了现象配置了流水表归档任务跑起来之后业务接口的响应时间翻倍监控上看到大量行锁等待。原因归档任务默认按条件全量扫没有限量、没有分批提交一个长事务持锁几分钟线上写全被挡住。解决加限量、加提交间隔、按主键推进并且放在低峰跑。# 小批量归档每批 1000 行每批独立提交批间休眠 pt-archiver \ --source h127.0.0.1,P3306,uarch,ppassword,Ddemo,torder_flow \ --where created_at 2024-01-01 \ --limit 1000 \ --commit-each \ --sleep 0.2 \ --purge \ --why-quit参数说明--limit 1000控制单批行数是控制锁范围最直接的参数--commit-each让每批单独提交避免一个巨型事务--sleep 0.2在批间留出喘息时间给线上业务让路--purge表示归档后删除源表数据不加就是只复制不删--why-quit输出退出原因排查任务提前结束很有用。归档条件里的时间列必须有索引否则每一批都是全表扫加多少--sleep都救不回来。5.3 binlog2sql 解析出来是空的现象填了文件、填了位点点获取 SQL结果是空列表或者只有零星几条。原因四个常见诱因。binlog 格式不是 ROW位点区间填反了或者超出文件范围库表筛选条件写错库名大小写、表名多空格目标操作是 DDL本来就没有行变更可解析。解决先用mysqlbinlog把区间内容打出来看确认里面有目标表的行事件再回到工具里填参数。# 确认位点区间内到底有没有目标表的行变更 mysqlbinlog --start-position857 --stop-position1183 -vv master-bin.000009 \ | grep -A 5 -i order_flow参数说明-vv会解码出行变更能直接看到### UPDATE这样的标记grep用来快速定位表名注意 binlog 里的库表名是全限定形式demo.order_flow。如果这段输出里只有 Query 事件没有行事件说明这段是 DDL回滚这条路走不通只能靠备份或手工逆向语句。5.4 schema 比对生成的 DDL 直接执行报错现象两个环境做结构同步比对结果生成了一串 DDL看着很合理执行到一半报索引名重复或者字段类型不兼容。原因比对只覆盖表结构不覆盖数据也不判断目标库的现状。索引名在 MySQL 里是表级唯一的源库和目标库各自有同名索引生成的语句就会冲突字段类型收窄时如果目标表已有超长数据执行直接失败字符集不同也会让看似一样的字段产生差异。解决生成的同步 SQL 和回滚 SQL 一起看先在预发环境跑一遍重点检查三类语句加唯一索引先查有没有重复值、改字段类型先查最长值、删字段先确认没人用。-- 加唯一索引前先确认没有重复值否则 ALTER 会失败 SELECT user_id, COUNT(*) AS cnt FROM demo.t2 GROUP BY user_id HAVING cnt 1; -- 改字段类型前先确认现有数据长度 SELECT MAX(CHAR_LENGTH(ename)) AS max_len FROM demo.t2;参数说明HAVING cnt 1筛出的就是会阻塞唯一索引创建的行CHAR_LENGTH按字符算长度LENGTH按字节算判断能不能收窄到某个VARCHAR(n)时用前者更准。比对工具给出的是建议不是保证能执行的脚本这一步的人工确认省不掉。5.5 账号建好了、权限也授了应用还是连不上现象账号管理页面里创建了账号勾了增删改查和改表结构应用侧仍然报 Access denied。原因账号是按 host 匹配的页面上建的是app_user%而应用连过来的来源网段匹配到的是另一条更具体的记录或者存在一条更早的、权限更小的同名账号另一种情况是账号的认证插件和客户端不匹配。解决直接查实际生效的授权不要只看页面展示。-- 查这个账号在 MySQL 里的真实定义和授权 SELECT user, host, plugin FROM mysql.user WHERE user app_user; SHOW GRANTS FOR app_user%;参数说明host决定了匹配优先级具体网段优先于%所以出现两条记录时实际生效的往往是更具体的那条plugin字段能看出认证方式客户端版本低时可能不支持新的认证插件。确认之后要么删掉多余的旧账号要么按实际来源重建一条改完再让应用重连验证别只看页面上的绿勾。6. 快速定位把这套顺序固化成肌肉记忆排查这类问题最怕的是东一榔头西一棒子。我自己总结了一条从外到内的顺序五分钟内能把问题收敛到某一层剩下的就是照着上面章节处理。第一步看报错发生在哪一层。是检测阶段红解析和规则、提交后不动流程和通知、执行报错实例和环境还是执行成功但业务异常锁、回滚、数据。层定错了后面全白干。第二步把提示原文抄出来。平台的提示、MySQL 的错误码、从库的复制错误三类提示指向完全不同的地方凭印象转述最容易失真。第三步用最小命令验证。结构问题用SHOW CREATE TABLE权限问题用SHOW GRANTS配置问题用SHOW VARIABLES阻塞问题用information_schema.innodb_trx加进程状态页对照。一条命令能确认的事不要靠猜。现象第一眼先看常用命令或页面检测一片红提交按钮灰提示里是 syntax 还是规则名工单详情提示原文高危语句提交即驳回语句有没有 WHERE、是不是 DDL改写成分批语句工单卡在待审核当前节点挂在谁身上工单详情 右上角通知执行报错但检测通过表结构、账号权限、长事务SHOW CREATE TABLE、SHOW GRANTS回滚 SQL 是空的操作类型、binlog 三项配置SHOW VARIABLES LIKE binlog%杀会话后又回来是否连接池重试、是否大事务回滚中SHOW FULL PROCESSLIST磁盘告警想清 binlog从库已消费到的位点SHOW REPLICA STATUS第四步确认修复后再复验一次。改完规则、补完权限、杀完会话都要回到原来的入口重跑一遍确认同样的问题不再出现而不是看日志没报错就收工。血泪经验是变更前先花两分钟确认 binlog 三项配置和从库位点比出事之后花两小时从 binlog 里捞数据划算得多。从那以后我每次提工单都强制走一遍「检测 → 权限 → binlog 配置 → 回滚语句能不能生成」这四步哪怕是很小的一个 UPDATE 也照做因为翻车从来不挑语句大小。希望帮到你。本文还有配套的精品资源点击获取