查阻塞源需用show full processlist和information_schema.processlist过滤可疑线程,结合innodb_trx与lock_waits定位持锁事务,优先kill query,无效则kill connection,并批量生成脚本执行,事后核查回滚状态。

查阻塞源:别只看 SHOW PROCESSLIST,要结合 INFORMATION_SCHEMA.PROCESSLIST 过滤
单纯执行 SHOW PROCESSLIST 很容易漏掉真正卡死的查询——它默认截断 Info 字段(最多 100 字符),且不显示超长运行时间。一个执行了 1800 秒的 SELECT ... JOIN ... GROUP BY 可能只显示 SELECT * FROM orders WHE,根本看不出语义。
正确做法是:
- 用
SHOW FULL PROCESSLIST看完整 SQL 文本 - 用
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND STATE IN ('Locked', 'Waiting for table metadata lock', 'Sending data') AND TIME > 60查运行超 60 秒、处于可疑状态的线程 - 务必排除
User = 'system_user'或User = 'event_scheduler',这些是系统内部线程,杀错会引发复制中断或定时任务失效
KILL QUERY 还是 KILL CONNECTION?看线程当前状态再决定
KILL QUERY 和 KILL CONNECTION 是 MySQL 5.7.6+ 提供的两个细粒度命令,不是所有场景都适合直接 KILL 1234:
-
KILL QUERY 1234:只终止该连接当前正在跑的 SQL,连接本身保持活跃(Command变成Sleep),适合只想打断一个慢SELECT,但还想让应用复用这个连接 -
KILL CONNECTION 1234:连带关闭整个 TCP 连接,客户端会收到Lost connection to MySQL server during query,适合连接本身已卡死(比如处于Waiting for table metadata lock状态且对KILL QUERY无响应) - 如果
KILL QUERY执行后,STATE在几秒内没变回Sleep,立刻升级为KILL CONNECTION
确认是否真被阻塞:查 INFORMATION_SCHEMA.INNODB_TRX 和锁等待链
仅靠 PROCESSLIST 不足以判断谁在阻塞谁。真正的阻塞源头往往藏在事务锁层面:
- 运行
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY TRX_STARTED DESC,重点关注TRX_STATE = 'RUNNING'且TRX_WAITING_LOCK_ID IS NOT NULL的事务 - 再查
SELECT * FROM performance_schema.data_lock_waits(MySQL 8.0+)或SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS(MySQL 5.7),获取BLOCKING_TRX_ID对应的阻塞者 - 把
BLOCKING_TRX_ID映射回INNODB_TRX表中的TRX_ID,就能定位到那个没提交、还在持锁的源头事务
批量终止前先生成脚本,别手写 KILL
手动一个一个 KILL 容易眼花看错 ID,也难保证原子性。更稳妥的方式是先生成语句,再审阅执行:
- 用
SELECT CONCAT('KILL QUERY ', id, ';') FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND STATE IN ('Locked', 'Waiting for table metadata lock') AND USER NOT IN ('root', 'system_user') - 把结果复制进客户端执行;注意两点:
– 别在生产环境直接INTO OUTFILE后SOURCE,文件路径权限和 SELinux 可能拦截
– 务必排除root用户——DBA 自己跑的维护脚本也可能被误杀
杀完别就走,马上查 SHOW ENGINE INNODB STATUS\G 的 TRANSACTIONS 部分,确认没有 TRX_STATE = 'ROLLING BACK' 且耗时过长的事务残留——大事务回滚可能持续数分钟,期间仍会持续占锁。











