简介:《archery使用手册》是一份面向SQL审核、查询平台使用者和MySQL运维人员的实操文档,围绕Archery的审核规则、工单流程、SQL优化与实例管理展开,适合开发、测试及DBA在数据库规范落地和日常排障中参考。压缩包共1个doc文件,大小约1.2MB,内容按功能详解与实践案例组织,便于集中查阅。手册具体梳理SQL语法与规范审核、高危语句驳回、定时或立即执行及回滚SQL,也覆盖执行计划分析、慢SQL统计、binlog清理、会话与事务终止、锁信息排查、账号授权和动态参数配置;PTArchiver、Binlog2SQL、SchemaSync等插件的用途与操作示例亦有涉及。已有1479人学习,可作为快速熟悉Archery功能边界、对照实践流程与查漏补缺的参考资料。
1. Archery 不是只做审核:一次误更新之后我重新读了这份手册
凌晨收到磁盘告警,登上去发现一条没走任何审核的 UPDATE 打在大表上,备份是有的,binlog 也在,可真要从里面捞出一句正确的回滚语句,团队里没人敢拍胸脯。这种翻车现场我见过不止一次。Archery 使用手册这份材料要解决的就是这条链路上的断点:它把 SQL 审核、工单执行、回滚语句生成、会话与锁的排查、binlog 解析、表结构比对串成一个闭环,让每次变更留审核记录,让每句 DML 都有后悔药。它面向的是每天要碰库的人:研发提工单、测试做环境验证、DBA 处置慢查询和阻塞。下面按我实际拆过一遍的顺序,把流程、参数和坑位摊开。
2. SQL 审核工单怎么走:从提交检测到回滚 SQL 落盘
很多人把审核理解成"提交前点一下检测按钮",实际用下来会发现,真正的价值在于规则前置和回滚兜底这两头。审核只是中间一段,前面要有可执行的规范,后面要有能验证的回滚。这一章按规则、环境、操作、回滚四段拆。
2.1 审核规则先立住:主键、注释、高危语句三条硬线
Archery 的审核链路是先把提交的 SQL 解析成语法树,再逐条套自定义规则,返回按等级分类的结果:error 级直接阻断提交,warn 级只提示不拦。所以规则配得好不好,决定了这个平台是帮你把关还是变成走流程的橡皮图章。
我一般会把硬线压到三条:建表必须有主键、表和列必须有注释、高危语句自动驳回。第一条关系到后续数据订正和归档能不能定位到行,没主键的表在 pt-archiver 归档时几乎没法安全分批;第二条关系到后来人读不读得懂这张表,尤其是字段上百的宽表;第三条是保命的,无 where 的 update/delete、drop table、truncate 这类语句一旦放过,后面所有流程都白搭。
先看一条能顺利过检的建表语句:
-- 提交前自己先过一遍:主键、注释、字符集、索引命名都在 CREATE TABLE `order_flow` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `order_no` varchar(32) NOT NULL COMMENT '订单号', `amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '金额', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_order_no` (`order_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单流水表';再看一条大概率被 error 拦下的:
-- 缺主键、表和列都没有注释,规范类规则会逐条报出来 CREATE TABLE order_flow_bak ( order_no varchar(32) NOT NULL, amount decimal(12,2) );这两段的差别不在语法,语法都合法。差别在解析器把 AST 拆开后能提取到的元信息:有没有 primary key 节点、comment 属性是不是空、字段类型有没有超长、字符集是不是统一。参数上要留意规则等级,同一条规则在不同实例上可以配成 error 或 warn,比如历史库的存量表注释缺失较多,一刀切成 error 会让所有变更都卡住,这种库我一般先配 warn 跑两周,把存量问题清完再收紧。
| 规则项 | 判定依据 | 平台处置 | 建议 |
|---|---|---|---|
| 建表无主键 | AST 中缺少 PRIMARY KEY 定义 | error,阻断提交 | 所有新表强制 |
| 表/列无注释 | comment 属性为空 | error 或 warn | 新库 error,存量库先 warn |
| 高危 DML | 无 where 的 update/delete | 自动驳回 | 一律 error,不给例外 |
| 字符集不一致 | 表字符集与库默认不同 | warn | 统一 utf8mb4 |
| 索引命名 | 索引名不匹配约定前缀 | warn | 便于后期排查 |
规则配完还要有人维护。常见做法是每季度拉一次被驳回的工单,看看哪些规则误伤率高、哪些规则从来没人触发,前者放宽,后者说明开发已经养成习惯或者规则本身失效,该删就删。
2.2 开发环境与测试环境的两套流转逻辑
同一套平台,开发和测试两条流程的发起人、审核链、执行人都不一样,弄混了最容易出现"工单提错环境"的低级问题。
开发环境的链路是:研发工程师发起 → 项目经理审核 → 最后一级通过后选择立即执行或定时执行。这条链多一道业务负责人的确认,因为开发库往往是多人共用,一次表结构变更可能影响同库的其他模块。
测试环境的链路是:测试同事从 git 上取开发已提交的 SQL 文件 → 在测试环境发起审核 → 测试同事自己审核并执行。发起和审核是同一个人,看着像没审核,其实是把把关点前移到了 SQL 检测那一步:检测不过就提交不了,提交了才轮到自己点通过。
| 维度 | 开发环境 | 测试环境 |
|---|---|---|
| 发起人 | 研发工程师 | 测试工程师 |
| SQL 来源 | 本地开发整理 | git 上开发提交的文件 |
| 审核链 | 项目经理 | 测试自己(审核+执行) |
| 执行时机 | 立即或定时 | 立即为主 |
| 主要风险 | 影响多人共用库 | 自审自执行跳过检测 |
测试环境这条链最容易出的问题,是测试同学拿到文件直接点提交、跳过 SQL 检测。平台的检测是提交前的独立动作,不是提交时自动跑的,漏点一次等于规则全部失效。我习惯在流程里加一条约定:任何环境提交前必须先点检测,检测结果截图跟工单一起留档。
2.3 提交、检测、审批、执行四步实操
把一次工单从头走到尾,动作其实只有四步,但每一步都有容易漏的细节。
第一步,准备 SQL 文件。文件名带上日期、库名、变更类型,语句之间用分号分隔,避免一个文件里混着 DDL 和 DML 却没标注。文件编码统一 UTF-8,中文注释才不会在解析时变成乱码导致误判。
第二步,发起工单。选实例、选库、上传文件或直接粘贴,填变更说明。点"SQL 检测"后看结果:出现 error 就必须改 SQL 重新提交,warn 可以带着说明继续。检测通过再点"SQL 提交",这时工单才真正进入审核队列。
第三步,审批。审核人登录后点右上角通知按钮看待办,逐条看 SQL 和检测结果。这一步别只看有没有 error,还要看变更窗口:大表加索引这类操作即使语句合规,也可能在业务高峰把 IO 打满。最后一级审核通过后,选择"立即执行"或"定时执行"。定时执行的价值就在这里,把变更压到低峰窗口,不用人半夜守着点按钮。
第四步,执行后验证。执行成功不等于变更正确,尤其是 DML 类工单,要回查影响行数和数据分布。
提交前我会在本地先跑一遍自检,省得来回改:
-- 1. 找出没有主键的表(返回结果为空才放心) SELECT t.table_schema, t.table_name FROM information_schema.tables t LEFT JOIN information_schema.statistics s ON s.table_schema = t.table_schema AND s.table_name = t.table_name AND s.index_name = 'PRIMARY' WHERE t.table_schema = 'baidd' AND t.table_type = 'BASE TABLE' AND s.index_name IS NULL; -- 2. 找出缺列注释的字段 SELECT table_name, column_name, column_type FROM information_schema.columns WHERE table_schema = 'baidd' AND (column_comment = '' OR column_comment IS NULL); -- 3. 看表体量,决定要不要改成定时执行 SELECT table_name, table_rows, ROUND(data_length / 1024 / 1024, 2) AS data_mb FROM information_schema.tables WHERE table_schema = 'baidd' ORDER BY data_length DESC LIMIT 10;第一段用 left join 反查 statistics 里没有 PRIMARY 索引的表,注意要把 table_type 限定成 BASE TABLE,否则视图会被误报。第二段直接扫 columns 的 comment 字段,返回的行就是审核时会被标出来的列。第三段看表体量和数据量,data_mb 超过一定阈值(我一般按 5GB 划线)的变更就不要选立即执行了,走定时。
2.4 回滚 SQL 的生成与验证
工单执行完之后,页面上可以"查看回滚 SQL"和"下载回滚 SQL"。生成逻辑是把原语句按类型反向推导:insert 对应 delete、delete 对应 insert、update 用原值反写 where 条件。这一步是整条链路里最像后悔药的部分,但它的边界必须说清楚。
DML 能回滚,DDL 只能回滚结构、回滚不了数据。drop column 生成的回滚语句是 alter table add column,列加回来了,里面的值没了。truncate 更是连结构都不保留。所以看到工单里有 DDL 时,回滚 SQL 只能当结构参考,真正的兜底还是执行前的备份。
回滚 SQL 下载下来别急着存网盘。我一般会在影子库先执行一遍:拿一份同结构的空库,把回滚语句跑通,确认语法没问题、where 条件能命中预期行数、没有漏掉 limit。这一步花十分钟,能挡住后面几小时的排查。
| 原操作 | 回滚语句形态 | 数据能否恢复 |
|---|---|---|
| insert | delete ... where 主键 | 能 |
| update | update ... set 原值 where 主键 | 能 |
| delete | insert ... values 原行 | 能 |
| alter table add column | alter table drop column | 仅结构 |
| alter table drop column | alter table add column | 数据丢失 |
| truncate / drop | 无有效回滚 | 不可恢复 |
提示:回滚 SQL 生成后要检查 where 条件是否带上了完整主键。缺主键的 update 生成的回滚语句会按原 where 条件反写,一旦原条件是范围匹配,回滚可能波及更多行。
3. SQL 优化与慢日志:执行计划里那几个字段到底怎么看
审核管的是"能不能执行",优化管的是"执行得快不快"。这两件事在 Archery 里是两个入口,但排查思路是连着的:慢日志告诉你哪条 SQL 慢,SQL 分析告诉你为什么慢。
3.1 SQL 分析入口与优化建议的取舍
在 SQL 优化页面贴入语句,平台会返回执行计划和优化建议。拿手册里的例子:SELECT * FROM baidd.emp WHERE ename='dan_1';分析结果会提示把select *改成具体字段,改完再分析就变成 OK。
为什么select *在这类规则里被判问题,值得说清楚。一是覆盖索引失效,本来ename上的索引能直接返回结果,带*就得回表取整行;二是宽表传输成本高,几十个字段全部拉回客户端,网络和内存都要付代价;三是表结构变更后,*的返回列会跟着变,依赖固定列序的代码容易出问题。
但优化建议不能照单全收。平台给的索引建议有时会和你已有的索引重复,或者建议的字段区分度极低(比如性别、状态位),建了也用不上,反而拖慢写入。我的判断顺序是:先看执行计划里 type 是不是 ALL,再看 rows 估算行数,最后才看建议要不要采纳。
-- 分析前先确认表上有哪些索引,避免重复建 SHOW INDEX FROM baidd.emp; -- 看语句实际走了哪个索引 EXPLAIN SELECT id, ename, dept_no FROM baidd.emp WHERE ename = 'dan_1';第一段返回索引名、列序、基数,基数(Cardinality)越低说明这列区分度越差。第二段把*换成具体字段后再 explain,对比 key 列有没有变化,这是验证优化是否生效最直接的办法。
3.2 执行计划字段解读
执行计划里字段不少,日常排查真正需要盯的就几个。
| 字段 | 含义 | 关注点 |
|---|---|---|
| type | 访问类型 | ALL 全表扫描要处理,index 次之,range/ref/eq_ref 可接受 |
| possible_keys | 可能用到的索引 | 为空说明压根没索引可用 |
| key | 实际使用的索引 | 与 possible_keys 不一致时要看为什么没选中 |
| key_len | 索引使用长度 | 比预期短说明联合索引只用了前几列 |
| rows | 预估扫描行数 | 数量级偏大就要考虑改写或加索引 |
| filtered | 过滤后剩余比例 | 很低说明 where 条件没被索引覆盖 |
| Extra | 附加信息 | Using filesort、Using temporary 是需要优化的信号 |
type 从差到好的顺序大致是 ALL → index → range → ref → eq_ref → const。看到 ALL 不一定要立刻加索引,小表全扫可能比走索引还快,rows 只有几百行的表可以放一放。真正的血泪经验是 key_len:联合索引 (a,b,c),如果 key_len 只等于 a 的长度,说明 b 和 c 没用上,常见原因是查询条件里跳过了 b 直接用了 c。
Extra 里的 Using filesort 表示排序没走索引,数据量大时会写临时文件;Using temporary 表示用了临时表,常见于 group by 和 distinct。这两个信号同时出现,基本可以判定这条 SQL 需要改写。
3.3 慢日志统计与索引确认
慢 SQL 页面能看到慢语句列表和统计信息。统计维度一般包括执行次数、平均耗时、最大耗时、扫描行数。排序方式很关键:按总耗时排,找出来的是高频低耗的语句,优化收益大;按单次最大耗时排,找出来的是偶发的重查询,往往是某个报表或者导出任务。
慢日志本身是采样,受 long_query_time 阈值控制,低于阈值的语句不会记录。所以看到"没有慢 SQL"不等于没有问题,可能只是阈值设得太宽。我一般把阈值压到 1 秒,先跑一周看整体分布,再决定要不要放宽。
-- 按平均耗时排序,找出最该优先处理的语句 SELECT digest_text, count_star, ROUND(avg_timer_wait / 1e12, 3) AS avg_sec, ROUND(max_timer_wait / 1e12, 3) AS max_sec, sum_rows_examined FROM performance_schema.events_statements_summary_by_digest WHERE schema_name = 'baidd' ORDER BY avg_timer_wait DESC LIMIT 20;这段查的是 statements summary 表,digest_text 是归一化后的语句模板(参数被替换成 ?),所以同一类语句会聚合成一行。avg_timer_wait 单位是皮秒,除以 1e12 换成秒。sum_rows_examined 是累计扫描行数,这个值除以 count_star 得到的平均扫描行数,比耗时更能反映索引是否合理——平均扫描几万行才返回几条记录的语句,优先处理。
拿到慢语句后回到 SQL 分析页面贴进去看执行计划,两步串起来才算闭环。只优化不加验证是另一个坑:改完 SQL 要在测试环境用相近数据量跑一遍,小数据量下执行计划可能选错索引,上线后才暴露。
4. 实例管理联动排查:binlog、会话、事务与锁
实例管理这一块默认只有管理员账号有权限,权限收紧是对的,因为这里的每个按钮都能直接影响线上。四个功能看似独立,实际排查时经常要连着用:会话列表看到阻塞,转到锁信息确认阻塞方,再看事务信息判断是不是长事务没提交。
4.1 binlog 清理的顺序陷阱
磁盘空间不足时,清理 binlog 是最快的释放手段。在实例列表里选中某个 binlog,平台会把这个文件以及它之前的所有 binlog 一起删除。注意这个"之前"是关键字:如果你选中的是中间某个文件,前面几个也会一起没。
这个设计不是平台的问题,是 MySQL 本身的机制决定的,binlog 只能按顺序从最早的开始删。但操作时很容易误判成"只删选中的这一个"。我一般按三步走:先确认从库同步到了哪个文件、确认没有延迟很大的从库还依赖旧文件、确认最近的备份对应的 binlog 起点在哪。
-- 1. 从库同步到哪个文件、延迟多少 SHOW SLAVE STATUS\G -- 关注 Master_Log_File、Read_Master_Log_Pos、Seconds_Behind_Master -- 2. 当前正在写的 binlog SHOW MASTER STATUS; -- 3. 手工清理时对比平台操作(一般在平台点,命令行仅作核对) -- PURGE BINARY LOGS TO 'mysql-bin.000020';第一段在从库上执行,Master_Log_File 表示从库已经读到主库的哪个文件,Seconds_Behind_Master 是延迟秒数。清理前必须确认要删的文件都小于这个位置,否则从库会报错中断。第二段在主库执行,拿到当前文件号作为边界参考。第三段是 MySQL 原生命令,只用来核对平台操作的范围对不对,实际清理还是走平台,因为平台会记录操作人和时间。
注意:清理 binlog 前确认最近一次全量备份的起始位置。如果备份对应的 binlog 被删掉,这份备份就没法做基于时间点的恢复。
4.2 会话管理必须先勾"完整 INFO"
进程状态页面能看到当前正在执行的 SQL。右上角选择实例和 command 类型,默认是 query,只看查询类进程;排查问题时切到 All,把 Sleep、Binlog Dump 这些也带上,才能看到全貌。
这里有个反复踩的坑:列表里的 INFO 列默认是截断的,长 SQL 只显示前面一小段,根本看不出问题。必须先勾上"完整 INFO",否则你会对着一句残缺的 SQL 排查半天。截断不是玄学,是为了避免一次拉几百条长语句把页面拖死。
定位到具体某条 SQL 造成阻塞后,点"终止会话"就能 kill 掉。但终止前要确认两件事:这条会话是不是在跑长事务、是不是已经执行了大半。一个跑了四十分钟的 alter table 被你 kill 掉,回滚过程可能比原操作还久。
4.3 事务与锁信息联合定位阻塞
事务信息页面看当前运行的事务,关键字段是 trx_mysql_thread_id,它对应的就是进程状态里的 THREAD ID。锁信息页面看等待关系,能看到等待事务的 SQL(也就是被阻塞的那条)和阻塞方的线程 id。
手册里给了一个很干净的复现方式,我在测试库照着跑过一遍:
-- 会话 A:开事务并更新 id=2 BEGIN; UPDATE baidd.t2 SET ename = 'baidd' WHERE id = 2; -- 会话 B:另一条连接执行,会被阻塞 UPDATE baidd.t2 SET ename = 'dan' WHERE id = 2;会话 A 执行完不提交,会话 B 就会卡住。这时候在锁信息页面能看到:等待事务的 SQL 是会话 B 那条 update,阻塞方的线程 id 指向会话 A。处理方式有两种,取决于业务:确认会话 A 是忘了提交,就直接按 trx_mysql_thread_id 在进程状态里搜到线程并终止;如果会话 A 正在跑重要的批量更新,就等它跑完,贸然 kill 会触发回滚。
排查顺序我习惯倒着来:先看锁信息确认有没有等待,再看事务信息确认阻塞事务开了多久,最后去进程状态里定位线程。反过来做的话,进程列表几百条,很难一眼找出问题。
-- 直接查锁等待关系,与平台页面对照 SELECT r.trx_id AS waiting_trx, r.trx_mysql_thread_id AS waiting_thread, r.trx_query AS waiting_query, b.trx_id AS blocking_trx, b.trx_mysql_thread_id AS blocking_thread, b.trx_query AS blocking_query FROM information_schema.innodb_lock_waits w JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;这段查的是 innodb_lock_waits 和 innodb_trx 的关联,waiting_thread 拿到后在平台进程页面搜,就是那个要终止的会话。blocking_query 有时为空,因为阻塞事务可能已经执行完语句处于 Sleep 状态,这时候要看 blocking_trx 的开始时间和状态判断。
4.4 账号管理与动态参数留痕
账号管理支持图形化建号、授权、改密、删号。建完账号必须单独授权,不会自动带上权限。授权时按最小权限给,一个只读报表账号就不要给 INSERT。
-- 平台授权背后的等价语句,用于核对权限是否符合预期 GRANT SELECT, INSERT, UPDATE, DELETE ON baidd.* TO 'app_rw'@'10.0.%'; SHOW GRANTS FOR 'app_rw'@'10.0.%';第一段是读写账号的典型授权,库级粒度。第二段核对实际生效的权限,重点看有没有意外的*.*或者 GRANT OPTION。平台操作完最好用这个语句复核一遍,图形界面偶尔会有勾选遗漏。
参数配置这一块能改实例的动态参数并记录修改历史。要区分动态参数和静态参数:innodb_buffer_pool_size 在 5.7 之后支持在线调整,但调整过程会占 IO;max_connections 可以直接改;而像 innodb_log_file_size 这种改了要重启才生效的,平台上改了不会立即体现,容易误判成没生效。改完参数一定要在历史记录里留一句变更原因,不然三个月后没人知道为什么这个值被调过。
4.5 结构比对与归档入口
实例管理之外还有两个常被忽略的能力。SchemaSync 用来读源库和目标库的表结构,自动生成同步用的 DDL 和对应的回滚 SQL。它只比对表结构,不比对数据,所以拿它做上线前的结构核对很合适,但别指望它发现数据不一致。
PTArchiver 解决的是大表历史数据堆积。线上流水表只保留最近三个月,更早的数据归档到历史库,配成定时任务后不用人工干预。归档前务必确认表有主键,否则分批删除没法定位行,容易锁表。
5. 常见问题与排查:五条踩坑记录
下面这几条是实际用下来反复出现的,每条按现象、原因、解决写。
第一条:SQL 检测全绿,执行时报错。
现象是工单检测通过、审批通过,点执行后返回字段不存在或者字符集不兼容。原因是检测阶段主要做语法解析和规范匹配,不做执行环境校验,SQL 里引用的表在目标库不存在、字段类型和值不匹配这类问题它发现不了。解决方式是在提交前先在目标库跑一次EXPLAIN或者SELECT ... LIMIT 0验证对象存在,工单里附上验证结果。
第二条:回滚 SQL 执行了,数据还是没回来。
现象是 DDL 工单执行后发现问题,下载回滚 SQL 跑完,表结构恢复了但数据空了。原因是回滚语句只还原结构,drop column、truncate 这类操作的数据在语句执行时就已经丢失。解决方式是所有含 DDL 的工单执行前做表级备份,回滚 SQL 只当结构参考,别当数据恢复手段。
第三条:清理 binlog 后从库报错中断。
现象是磁盘告警处理完,第二天发现从库同步停了,报找不到 binlog 文件。原因是清理时选中的文件晚于从库已同步的位置,前面被一起删掉了。解决方式是按 4.1 的顺序先查SHOW SLAVE STATUS,确认 Master_Log_File 之后再操作;已经出问题的从库需要重新做全量同步。
第四条:会话列表里看不到完整 SQL。
现象是排查阻塞时,INFO 列只有半句话,看不出是哪个业务。原因是没勾"完整 INFO",页面默认做了截断。解决方式是进页面第一件事就勾上这个选项,再选 command 类型为 All。这条踩过一次就会记住,属于纯粹的界面习惯问题。
第五条:binlog2sql 解析不出回滚语句。
现象是填入起始和结束位置后,返回结果为空或者报格式错误。原因通常有两个:实例的 binlog_format 不是 ROW,或者选的位置区间内只有 DDL。前者需要确认参数配置,后者是 binlog2sql 的固有限制,DDL 无法生成回滚。解决方式是先在实例参数里确认binlog_format=ROW,再通过SHOW BINLOG EVENTS看区间内的事件类型,只有 Query 事件(DDL)时不要指望回滚。
6. 进阶:用 binlog2sql 做一次可验证的数据回滚演练
前面说的回滚 SQL 是平台根据原语句推的,真正的兜底能力在 binlog2sql:从 binlog 里把实际执行过的 SQL 解析出来,再生成反向语句。这两者的差别在于,前者依赖工单记录,后者依赖磁盘上的 binlog,即使有人绕过平台直接连库改数据,也能捞回来。
演练步骤我一般这么走。先确认 binlog_format 是 ROW,这是解析的前提,STATEMENT 格式拿不到行级变更。再通过SHOW MASTER STATUS和SHOW BINLOG EVENTS定位误操作落在哪个文件、哪个位置区间。然后进工具插件页面选实例、填起始文件和起止位置,点获取 SQL。如果只是想确认改了什么,这一步就够了;要回滚就点 flashback 再获取一次,平台会返回反向语句。文件大时用异步获取,执行完会通知结果。
命令行版本适合在演练环境先验证一遍:
# 解析原始 SQL:看这段区间内到底执行了什么 python binlog2sql.py -h127.0.0.1 -P3306 -uuser -p'pass' \ -d baidd -t t2 \ --start-file='mysql-bin.000009' --start-pos=857 --stop-pos=1183 # 生成回滚 SQL:加 -B 参数,输出的是反向语句 python binlog2sql.py -h127.0.0.1 -P3306 -uuser -p'pass' \ -d baidd -t t2 \ --start-file='mysql-bin.000009' --start-pos=857 --stop-pos=1183 -B参数含义逐个数:-d指定库名,-t指定表名,两个都可省略,省略时解析全库全表但输出会很长;--start-file和--start-pos是解析起点,--stop-pos是终点,位置号可以从SHOW BINLOG EVENTS IN 'mysql-bin.000009'的结果里找;-B是 flashback 开关,输出 update 的反向 update、insert 的反向 delete。第一次跑建议先不加-B,看清楚原始变更再决定。
| 场景 | 参数组合 | 输出内容 |
|---|---|---|
| 确认改了什么 | 不加 -B | 原始 SQL |
| 生成回滚语句 | 加 -B | 反向 DML |
| 只要 insert 部分 | 加--only-dml --sql-type INSERT | 插入语句 |
| 去掉主键生成 | 加--no-primary-key | 无主键 insert |
回滚语句生成后不要直接往生产跑。我的做法是先导入影子库,比对影响行数和主键范围,确认无误再执行。DDL 的回滚别指望这个工具,它只处理 DML。
从那以后我每次做数据订正工单,都强制走一遍"定位 binlog 位置 → 解析原始 SQL → 生成回滚 → 影子库验证"这四步,哪怕只是改一行。多花十分钟,换来的是出问题时能当场把数据摆回去,而不是对着一堆备份文件干瞪眼。希望帮到你。
本文还有配套的精品资源,点击获取