简介《archery使用手册》是一份面向DBA、后端开发与运维人员的SQL审核与MySQL运维实践文档围绕Archery平台的核心能力展开适合需要搭建SQL工单流程、排查数据库性能与并发问题、规范建表与上线操作的技术人员参考。压缩包共1个doc文件约1.2MB以单一文档形式集中呈现平台功能说明、实践案例与操作示例便于按主题检索。内容覆盖SQL语法与规范审核、高危语句驳回、定时或立即执行及回滚语句生成也包含SQL分析优化建议、慢SQL统计、实例管理中的binlog清理、会话与事务查看、锁信息排查、账号和动态参数配置以及PTArchiver、Binlog2SQL、SchemaSync等插件的适用场景。已有1478人学习读者可从中获得从审核流程设计到实例运维排错的一整套参考思路并借助开发、测试环境的流程示例理解权限分工与执行闭环。1. archery 使用手册把 SQL 上线从口头约定变成可审计的工单很多人第一次接触 SQL 审核平台是因为线上出过一次“谁在什么时候改了这一列”的追问——翻聊天记录、翻 Git 提交、翻数据库慢日志最后发现改表语句是某个人在客户端里手敲的。archery 这个资源要解决的正是这个场景它把 SQL 提交、语法与规范检查、审批、执行、回滚语句生成串成一条有记录的链路同时把 MySQL 日常运维里最常用的会话、事务、锁、账号、binlog 清理和几个工具插件收在同一个界面里。这份使用手册覆盖了 SQL 审核与优化、实例管理、pt-archiver 归档、binlog2sql 解析回滚、schema 比对同步这几块内容适合正在建研发自测流程的团队、需要给非 DBA 开放受控查询入口的运维以及想把“建表必须有主键、必须有注释”这类规范真正卡住的人。它不是拿来替代数据库本身的工具而是一层把人和库隔开的审核闸门。下面按“流程怎么跑、SQL 怎么优化、实例怎么排障、插件怎么用、坑在哪”的顺序拆开讲。2. SQL 审核工单的完整链路从提交到回滚脚本落盘archery 的核心不是“能执行 SQL”而是“执行前必须先被规则过一遍”。理解这一点的关键是把它看成一个工作流引擎加一个 SQL 解析器解析器负责告诉你这条语句在语法上对不对、在规范上合不合格工作流负责决定谁提交、谁审、审完什么时候执行。手册里给的两条流程线研发到项目经理、测试自己提自己审其实就是同一套引擎的两种审批节点配置。把这条链路跑通后面所有功能才有意义。2.1 审核流程的两个角色模型与选择依据手册里的开发环境流程是“研发工程师 → 项目经理”两级测试环境是“测试同事发起 → 测试同事审核并执行”一级自审。这两种配置不是随便定的而是对应两种风险等级开发环境的变更最终要进生产所以需要一个不完全懂技术但能判断业务影响的人做最后一道闸测试环境的数据可丢所以让发起人自审减少等待。落到配置层面常见做法是把审批节点按“环境 库”绑定而不是按人绑。这样新增一个研发不需要改流程只要把他放进对应角色组。判断标准很简单如果某类变更出错后的恢复成本高于一次审批的等待成本就加一级否则就减到一级。提示一级自审不等于没有约束规则检测这一关仍然会拦住语法错误、缺主键、缺注释、高危语句人工审核只是第二道。2.2 提交 SQL 工单时的字段与检测动作发起工单需要填的信息一般包括目标实例、目标库、是否需要回滚、执行方式、SQL 文本或上传文件。填完之后先点“SQL 检测”这一步只做解析和规则匹配不碰数据库。检测结果是 error 就不能提交必须改到 warning 或通过。下面这段不是 archery 的代码而是把手册里“检测发现问题 → 修改 → 再检测”这个循环固化成脚本的思路用于在提交前本地预检减少反复#!/usr/bin/env bash # 本地预检脚本把待提交的 SQL 先做一轮粗筛减少在 archery 里来回改的次数 SQL_FILE$1 # 1. 拦截明显的高危全表更新/删除 grep -inE ^[[:space:]]*(update|delete)[[:space:]][a-zA-Z0-9_][[:space:]]set $SQL_FILE \ | grep -viE where \ echo [BLOCK] 检测到无 WHERE 的 UPDATE/DELETEarchery 高危规则会直接驳回 # 2. 建表语句缺主键、缺注释的粗查 grep -inE create[[:space:]]table $SQL_FILE /dev/null { grep -qi primary key $SQL_FILE || echo [WARN] 建表未发现主键定义 grep -qi comment $SQL_FILE || echo [WARN] 建表未发现注释 } # 3. 输出语句条数便于和工单里填的数量核对 echo 语句条数(按分号估算): $(grep -o ; $SQL_FILE | wc -l)这段脚本的定位是“后悔药前置”在正式提交前把最容易被规则打回的三类问题先找出来。逻辑上它只做文本级匹配不做语法树解析所以会有误报比如delete出现在字符串常量里。参数上$1指向 SQL 文件路径grep -viE where这一层是为了找出“UPDATE ... SET 后面没有 WHERE”的形状实际使用时按自己的规则调整。真正在 archery 里点“SQL 检测”时看的是解析器返回的结果条目每条会标明是 error 还是 warning、命中哪条规则、涉及哪一行。error 一律阻断warning 可以带理由提交由审核人判断。2.3 审核通过后的执行策略与定时执行最后一级审核通过界面会给两个选项立即执行、定时执行。选择依据是业务低峰期——DDL 在大表上会持锁即使在线 DDL 也有元数据锁窗口所以结构变更一般排到低峰。定时执行的价值还在于它把“审核通过”和“真正落库”解耦审核人可以白天审执行放在凌晨。执行方式上有两种粒度工单整体执行或者按语句分批。大变更建议拆成多个工单一条 DDL 一个工单这样回滚时边界清晰出问题只需回退其中一条而不是整包回滚。2.4 回滚 SQL 的生成与使用边界手册里明确写了“下载回滚 SQL”和“查看回滚 SQL”两个入口。回滚语句是在提交工单时由平台根据变更前的数据状态生成的这一点决定了它的可靠性边界变更类型是否可自动生成回滚说明INSERT可生成对应的 DELETE依赖主键或唯一键定位UPDATE可生成反向 UPDATE需要能定位到原行DELETE可生成对应的 INSERT要求原行数据可被完整取回DDL建表/改列/删列不可结构变更无法自动反向需人工准备回滚方案注意删列这类操作即使平台给了回滚入口也不要指望它。执行前把表结构和数据做一份备份是这条流程里唯一真正的后悔药。3. SQL 优化与慢日志把执行计划和规则命中翻译成动作审核拦的是“能不能上”优化解决的是“上了之后跑不跑得动”。archery 这块给了两个入口对单条 SQL 做分析拿优化建议以及查看慢 SQL 及其统计信息。这两者要配合用单条分析解决已知问题慢日志统计帮你找到还没被发现的那些。3.1 用 SQL 优化入口读执行计划手册里的示例是SELECT * FROM baidd.emp WHERE enamedan_1;分析后给出建议把SELECT *改成具体字段后结果为 OK。这个例子的价值不在结论而在它展示的判断路径先看有没有走索引再看取了多少列。常见做法是把分析结果里的几项按顺序读访问类型type出现ALL说明全表扫描出现index说明扫全索引这两种都要关注预估扫描行数rows和表的总行数比比例高就说明索引选择性不够Extra 列出现Using filesort、Using temporary意味着额外排序或临时表。把这几项和 SQL 本身对照改法通常落在三处补索引、改写成能命中已有索引的形状、减少返回列。SELECT *的问题不只是多取数据更在于它让覆盖索引失效原本能只走索引的查询被迫回表。3.2 慢日志统计的读法与阈值设定慢日志这一块给出的信息是“哪些语句慢、慢了多少次、平均多久”。读的时候不要只按最慢排序而要看“总耗时 平均耗时 × 次数”。一条平均 200ms 但每分钟跑上千次的查询对系统的影响远大于一条偶发的 3 秒查询。阈值设定上long_query_time不建议一上来就设成 1 秒那样会把大量中等查询漏掉。可以先按 0.5 秒采集一段时间统计出业务查询的耗时分布再回头定这个值。-- 查看当前慢日志相关参数确认采集是否真的开着 SHOW VARIABLES LIKE slow_query_log; SHOW VARIABLES LIKE long_query_time; SHOW VARIABLES LIKE log_queries_not_using_indexes; -- 按总耗时排序看慢日志聚合示意实际表名依平台实现而定 SELECT sql_text, count_star AS exec_count, ROUND(sum_timer_wait / 1e12, 3) AS total_sec, ROUND(avg_timer_wait / 1e9, 3) AS avg_ms FROM slow_log_summary ORDER BY sum_timer_wait DESC LIMIT 20;第一段是确认采集开关log_queries_not_using_indexes打开后会记录未走索引的语句排查阶段有用但长期开着会让慢日志膨胀。第二段是聚合读法按sum_timer_wait降序而不是按平均耗时就是为了抓住“高频中等慢”的那批语句。字段名按平台的实际实现可能不同思路是固定的次数、总耗时、平均耗时三个一起看。3.3 从建议到落地的判断什么时候不该照做优化建议是规则给的规则不认识业务。三种情况要顶回去一是建议补的索引和已有索引高度重复加了只是徒增写入开销二是建议改写的语句涉及分页深翻改成子查询反而更慢三是建议去掉的字段其实是业务必需只是当前调用方没用。判断依据是这条 SQL 的调用频次和它在链路上的位置不是建议本身的对错。4. 实例管理排障会话、事务、锁三张表怎么串起来看实例管理是这套手册里最实用的部分因为它对应的是“线上正在出事”的场景。手册给的顺序是进程状态看正在执行的 SQL、事务信息看运行中的事务、锁信息看谁阻塞了谁三张表靠 thread id 串起来。这个串联关系值得单独讲清楚否则容易在界面上来回点却对不上号。4.1 进程状态command 类型过滤与完整 INFO进入进程状态默认只显示command query的会话也就是正在执行 SQL 的那些。排查阻塞时第一步是把过滤改成All因为阻塞方可能处于Sleep状态——它开了一个事务没提交自己不干活却握着锁。第二步是勾选“完整 INFO”。不勾的话 SQL 文本会被截断长语句只能看到开头而问题往往出在 WHERE 条件或者 JOIN 的那一段。这个勾选是排查时的必选项不是可选项。第三步是看Time列一个Sleep状态但 Time 很大的会话通常就是忘了提交或忘了断开的连接。4.2 事务信息与进程状态的 id 对应关系事务信息里的trx_mysql_thread_id对应进程状态里的 THREAD ID这是两个界面的唯一连接点。手册里给的终止路径是先在事务信息里拿到trx_mysql_thread_id再去进程状态里搜这个 id选中后终止会话。这个顺序不能反因为事务信息能告诉你这个事务持有哪些锁、跑了多久而进程状态只能告诉你它在执行什么。-- 当事务信息界面不好用时可以直接在库里查只读不改状态 SELECT trx_id, trx_state, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS trx_seconds, trx_mysql_thread_id, trx_query FROM information_schema.innodb_trx ORDER BY trx_started ASC; -- 锁等待关系谁在等谁 SELECT r.trx_id AS waiting_trx_id, r.trx_mysql_thread_id AS waiting_thread, b.trx_id AS blocking_trx_id, 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 r ON r.trx_id w.requesting_trx_id JOIN information_schema.innodb_trx b ON b.trx_id w.blocking_trx_id;第一段按事务开始时间升序最上面那条就是跑得最久的trx_seconds直接给出持续时间超过阈值就该处理。第二段是锁等待关系的直接映射blocking_thread就是你要去进程状态里搜的那个 id。这两个查询都是只读的platform 上对应的界面本质是在做同样的事。4.3 复现一次锁等待手册示例的完整操作手册里给的模拟很简洁会话 A 执行BEGIN; UPDATE baidd.t2 SET enamebaidd WHERE id2;不提交会话 B 执行UPDATE baidd.t2 SET enamedan WHERE id2;被阻塞。这个例子的关键在于会话 A 必须保持事务打开B 才会挂住。用 archery 观察时锁信息界面会显示等待事务的 SQL也就是 B 那条被阻塞的语句同时给出阻塞方的线程 id。此时正确处理不是立刻杀掉阻塞方而是先判断它是不是一个未提交的正常业务事务——如果是杀掉会回滚它已经做的修改如果它已经跑了很久且明显是连接泄漏才终止。注意终止会话是破坏性操作会回滚该事务的所有未提交变更。执行前确认这条会话对应的业务别把正在跑批的任务杀掉。4.4 binlog 清理与磁盘空间释放实例列表里的 binlog 清理操作语义是“选中某个 binlog 后它之前的所有 binlog 都会被删除”。这是 MySQL 的PURGE BINARY LOGS TO语义不是精确删除单文件。所以清理前要确认两点从库是否已经消费到该位置以及是否有基于 binlog 的恢复需求还在窗口期内。常见做法是先看当前写入位置和最早文件估算可清理范围再决定目标文件。清理动作本身不可逆删掉的 binlog 无法找回这一条是手册里最需要放慢手速的地方。5. 三个工具插件的落地姿势归档、解析回滚、结构比对手册里的三个插件对应三类重复劳动历史数据越堆越大、误操作后要从 binlog 里捞数据、多套环境的表结构对不齐。它们都是把命令行工具包了一层可视化理解底层工具的行为边界比记住界面按钮更重要。5.1 pt-archiver 归档把流水表的老数据挪走场景很典型一张流水表只保留最近三个月更早的数据要归档。pt-archiver 的做法是分批扫描、逐批搬迁、搬完删除避免一条大 DELETE 把库压垮。需要关注的参数不多但每个都影响行为参数作用设置建议--limit每批处理行数从 1000 起按库的压力调整--purge搬完后删除源表行不删除则只做复制--where归档条件用时间列做范围别用函数包列--sleep每批之间暂停秒数低峰期可设 0高峰期建议 1 以上--txn-size每事务行数与 limit 配合控制单事务大小--where那里最容易翻车写成DATE(create_time) 2024-01-01会导致索引失效全表扫。写成create_time 2024-01-01 00:00:00才能走索引。配置成自动任务时务必让任务可中断、可续跑归档不是一次性的活而是持续跑的。第一次跑建议只加--dry-run看它打算搬多少行。5.2 binlog2sql 解析能回滚 DML不能回滚 DDL手册里说得很清楚binlog2sql 从 binlog 解析出 SQL可以生成回滚语句但 DDL 操作无法回滚。这个边界必须记住因为误删列、误改字段类型之后靠这个工具是救不回来的只能靠备份。使用流程是给定位指定 binlog 文件名和起止位置拿到该区间内的语句。手册的例子是查master-bin.000009从 857 到 1183 之间的内容。位置信息可以从SHOW BINARY LOGS和SHOW BINLOG EVENTS里拿也可以按时间范围让平台换算。生成回滚语句时工具的按钮语义是反转把原 INSERT 变成 DELETE、原 DELETE 变成 INSERT、原 UPDATE 变成反向 UPDATE。前提是能定位到原行所以表上有主键或唯一键是硬条件没有主键的表解析出来的回滚语句可能影响多行。注意回滚语句生成后不要直接整段执行先挑几条在测试库验证确认 WHERE 条件唯一命中一行。5.3 schema 比对只比结构不比数据schema 同步工具的输入是源库和目标库输出是让目标库追上源库的 DDL以及对应的回滚 DDL。手册的例子是251库有几张表、249库只有一张比对后生成249相对251应该执行的 DDL。这里的语义方向要看清从目标追源别搞反。它只比对表结构不比对数据所以索引差异、列类型差异、默认值差异会被发现行数差异不会。用它做上线前检查很合适把预发和生产的表结构比一遍防止本地加了个字段忘了发布。比对结果里的回滚语句同样有边界加列的回滚是删列删列的回滚拿不回来数据。所以这套流程适合“结构对齐”不适合“结构回退”。6. 把这些流程跑顺的几个关键习惯用了一段时间之后我总结出这套手册里最容易被忽略的不是功能而是顺序和边界。功能都在界面上摆着真正决定这套平台好不好用的是几个前置判断。下面几条是我反复验证过的。第一工单粒度按语句拆不按需求拆。一个需求涉及三条 DDL就发三个工单。好处是执行可以分开排期回滚边界清晰出问题时能精确定位是哪一条导致。整包工单看起来省事实际是把风险捆在一起。第二回滚语句在提交前看一遍不要等出事再看。平台的生成逻辑依赖主键和唯一键如果某张表没主键生成的回滚 UPDATE 可能命中多行。提交工单时顺手点开回滚 SQL确认 WHERE 条件能唯一定位这个动作只要一分钟。第三进程状态里默认只看 query 是个陷阱。阻塞排查的第一步永远是切到 All 并勾上完整 INFO否则你看到的是“没有异常会话”而真正的持锁者正躺在 Sleep 里。第四定时执行的时间点要避开归档、备份、统计任务。这些任务本身就在吃 IODDL 撞上去会让元数据锁的等待时间成倍放大。排期前看一眼实例的定时任务表。第五清理 binlog 前先用从库的消费位置做一次核对。手册里写的“选中某个 binlog 后它之前的全删”是真实语义删完没有回收站。第六插件类的工具都建议先在测试库跑一遍同样的参数。尤其是 pt-archiver--purge加上错误的--where删错了数据只能靠备份恢复而备份可能还没覆盖到那一刻。有条血泪经验值得单独说某次在预发环境验证 schema 同步比对生成了 DDL 和回滚 DDL我直接执行了同步那段忘了回滚段里的删列操作是不可逆的。后来每次做结构比对我都会先看清楚哪一半是“往前”、哪一半是“退后”再决定点哪个按钮。从那以后凡是带“自动生成回滚”字样的功能我都强制自己先读一遍生成的语句本身再决定是否执行。希望这份手册的拆解能帮到你尤其是那几条边界早点知道能少走不少弯路。本文还有配套的精品资源点击获取