pt-kill默认不杀事务,必须显式加--kill或--kill-query;仅用--busy-time会误杀(如长执行但无锁)或漏杀(如State=Locked但TIME很短),须配合--match-state和--match-info精准识别锁等待/持有行为,并通过--ignore-*、--victims all、--kill-query及专用权限保障安全。

pt-kill 默认不杀任何事务,必须显式加 --kill 或 --kill-query,且仅靠 --busy-time 无法精准识别锁事务——它只会按执行时长“盲杀”,而真正持锁的线程可能状态是 Locked 或 Waiting for table metadata lock,不是单纯“运行久”。
为什么只用 --busy-time 30 会误杀或漏杀
超时锁事务的核心特征不是“执行时间长”,而是锁等待或锁持有行为。比如一个 UPDATE 卡在行锁上,INFORMATION_SCHEMA.PROCESSLIST 中状态可能是 Locked,但 TIME 字段可能只显示几秒(因为锁等待不计入执行时间);反过来,一个大 INSERT SELECT 执行了 120 秒,状态是 executing,但它未必持锁阻塞别人。
-
--busy-time 30只匹配PROCESSLIST.TIME > 30的线程,对State = Locked或Waiting for table metadata lock的线程完全无效 - 真正该杀的是:正在等锁(
TRX_STATE = 'LOCK WAIT')或已持锁且长时间未提交(TRX_STATE = 'RUNNING'且TRX_STARTED < NOW() - INTERVAL 30 SECOND) - 所以必须配合
--match-state和--match-info,不能只依赖时间阈值
怎么写安全有效的 pt-kill 命令杀锁事务
目标是只动真正引发阻塞的线程,避开复制、监控、备份等关键连接。以下参数组合经生产验证可行:
- 用
--match-state="Locked|Waiting for table metadata lock|LOCK WAIT"锁定可疑状态(注意:MySQL 8.0+ 的INNODB_TRX.TRX_STATE值为LOCK WAIT,但PROCESSLIST.State显示为Locked或类似描述,需按实际输出调整正则) - 补一层 SQL 特征过滤:
--match-info="FOR UPDATE|LOCK IN SHARE MODE|SELECT .* FOR UPDATE|UPDATE .* WHERE|DELETE .* WHERE",避免误伤纯SELECT - 排除安全线程:
--ignore-command="Binlog Dump,Change master,Start slave,pt-heartbeat,pt-online-schema-change"和--ignore-user="backup,monitor,replica" - 动作选
--kill-query而非--kill:中断当前语句即可,连接保持,应用重试更可控 - 必须加
--victims all(默认只杀一个),并配--limit 1防止一次杀太多(上线前先--print预览)
权限和运行方式不配好,命令等于没跑
即使参数全对,没权限或没日志,pt-kill 就是摆设:
- 用户必须有
PROCESS+CONNECTION_ADMIN(MySQL 8.0+)或SUPER(5.7 及以前),缺一不可;用root跑是反模式,应建专用账号:CREATE USER 'ptkiller'@'localhost' IDENTIFIED BY 'xxx'; GRANT PROCESS, CONNECTION_ADMIN ON *.* TO 'ptkiller'@'localhost'; - 不加
--log /var/log/pt-kill.log,你永远不知道谁被杀了、SQL 是什么、是否误杀——生产环境禁止裸奔 -
--interval 10是底线,太短(如1)会打爆 CPU;太长(如60)可能错过黄金处理窗口 - 首次上线务必先跑
--print模式,确认输出全是预期目标,再换--kill-query
KILL 后锁还在?那是回滚在后台跑
执行 pt-kill --kill-query 后,SHOW PROCESSLIST 显示状态为 Killed 是正常现象,不代表锁已释放。InnoDB 正在后台按 undo log 回滚,耗时取决于修改行数。若 INNODB_TRX.TRX_OPERATION_STATE = 'rolling back' 且 TRX_ROWS_MODIFIED 很大,就只能等——这时候再发一遍 pt-kill 不但无用,还可能干扰回滚进程。


















