MySQL中无严格“僵尸线程”定义,实指TIME>60秒且COMMAND='Sleep'、STATE为Waiting for table metadata lock或INFO为NULL的滞留连接;需结合业务谨慎KILL CONNECTION,避免误杀复制或大事务线程。

怎么判断哪些线程是僵尸线程
MySQL 里没有严格定义的“僵尸线程”,实际指的是 State 长期停滞、Command 为 Sleep 但已超时、或卡在 Locked/Waiting for table metadata lock 等不可推进状态的连接。这类线程不干活却占着 max_connections 和内存,还可能阻塞 DDL。
查它们最直接的方式是:
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE TIME > 60 AND COMMAND = 'Sleep';
重点关注:TIME > 60(单位秒)、STATE 为 Waiting for table metadata lock 或空但 INFO 为 NULL;如果 INFO 显示长事务 SQL,也得警惕——它可能没提交,锁一直挂着。
kill 哪些线程才安全
不能见 Sleep 就杀。MySQL 的 KILL 分两种:KILL CONNECTION(断开连接),KILL QUERY(只终止当前语句,连接保持)。误杀主从复制线程、备份线程、或正在执行大事务的连接,可能引发数据不一致或中断。
-
KILL CONNECTION适用于:确认该连接无业务关联(如开发测试连上来忘关)、USER是root但HOST是内网临时 IP、DB为空且TIME超过 300 秒 - 避免杀:
USER为replication的线程、COMMAND是Binlog Dump、STATE为Master has sent all binlog to slave - 若线程卡在
Waiting for table metadata lock,先用SHOW ENGINE INNODB STATUS\G查TRANSACTIONS部分,定位持锁者再 kill 它,否则杀等待者没用
kill 指令执行后没反应?常见原因
执行 KILL CONNECTION xxx 后线程仍出现在 PROCESSLIST 中,通常不是命令失败,而是 MySQL 正在清理资源,尤其当线程正持有锁、写入 buffer 或处于事务回滚阶段时,可能卡住几秒到几十秒。
更麻烦的情况是:KILL 后状态变成 Killed 却长期不消失——这说明线程在执行不可中断的底层操作(比如磁盘刷脏页、DDL 的 online rebuild)。此时只能等,强行重启 mysqld 是下策。
- 检查是否真执行了:
SHOW PROCESSLIST中目标线程的State变成Killed,说明命令已接收 - 确认用户权限:执行
KILL需要SUPER或CONNECTION_ADMIN权限(MySQL 8.0+),普通账号会报错Access denied; you need (at least one of) the SUPER or CONNECTION_ADMIN privilege(s) for this operation - 注意版本差异:MySQL 5.7 默认不支持
KILL QUERY对Sleep线程生效;8.0+ 支持更细粒度控制,但KILL本身仍不中断 I/O 密集型操作
自动化清理前必须设的防护线
脚本或定时任务自动 KILL 很危险。哪怕加了 TIME > 300 条件,也可能误伤慢查询接口的合法长连接。上线前至少配好三道防线:
- 在应用层统一设置
wait_timeout和interactive_timeout(建议 60–120 秒),比靠 DB 层清理更可控 - 给监控加告警:当
Threads_connected持续 > 80%max_connections且Threads_running很低,大概率是大量Sleep连接堆积 - 禁止脚本直接调
KILL CONNECTION,改用KILL QUERY先试探;记录每次 kill 的ID、USER、INFO到日志,方便事后追溯
真正难处理的从来不是“怎么 kill”,而是为什么这些连接不释放——多数时候是应用没正确 close() 或连接池配置不合理。盯着 PROCESSLIST 救火,不如花半小时查查应用端的连接使用模式。


















