应查information_schema.INNODB_TRX和INNODB_LOCK_WAITS定位阻塞,而非仅依赖SHOW PROCESSLIST;KILL CONNECTION才能释放锁,KILL QUERY无效;MDL锁需结合事务与进程信息综合判断。

查 SHOW PROCESSLIST 为什么看不到卡住的线程
不是所有阻塞都表现为活跃连接,SHOW PROCESSLIST 只显示当前有状态的线程(比如 Query、Sleep、Locked),但某些表锁可能由已断开但未清理的连接残留导致——此时线程状态是 Sleep 或直接消失,实际锁还在。
真正该看的是 information_schema.INNODB_TRX 和 information_schema.INNODB_LOCK_WAITS:
-
SELECT * FROM information_schema.INNODB_TRX\G—— 查正在运行的事务,重点关注TRX_STATE(如LOCK WAIT)、TRX_MYSQL_THREAD_ID -
SELECT * FROM information_schema.INNODB_LOCK_WAITS\G—— 查谁在等谁的锁,能定位阻塞源头 - 如果
INNODB_TRX里有长时间运行(TRX_STARTED很早)且没提交的事务,大概率就是它占着表锁不放
KILL 后线程还在?注意 KILL 和 KILL QUERY 的区别
KILL 默认只终止当前语句(类似 KILL QUERY),对持有锁的事务无效;必须用 KILL CONNECTION(或简写 KILL + 线程ID)才能干掉整个连接并回滚事务释放锁。
- 先确认线程ID:
SELECT ID, USER, HOST, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep'; - 若
STATE是Locked或Waiting for table metadata lock,且TIME持续增长,优先KILL CONNECTION <code>ID - MySQL 5.7+ 支持
KILL QUERY <code>ID,但仅中断语句,事务仍存活,锁不会释放 - 执行后立刻查
INNODB_TRX,确认对应TRX_MYSQL_THREAD_ID是否消失
遇到 Waiting for table metadata lock 怎么办
这不是 InnoDB 行锁,是 Server 层的元数据锁(MDL),常见于 ALTER、DROP、CREATE 等 DDL 操作被长事务阻塞。即使你没显式开启事务,一个未提交的 SELECT 也可能导致它。
- 典型场景:应用开了事务查了一张表,忘了
COMMIT或ROLLBACK,接着 DBA 在另一会话执行ALTER TABLE—— 此时ALTER就卡在Waiting for table metadata lock - 查源头:连上
INNODB_TRX+PROCESSLIST,找TRX_STARTED最早、COMMAND是Query或Sleep但INFO非空的线程 - 别急着
KILL,先看INFO字段是否包含可疑 SQL(比如大范围 UPDATE 或未结束的事务) - DDL 操作本身也会加 MDL,所以
SHOW PROCESSLIST里能看到两个线程:一个是ALTER卡住,另一个是它在等的持有者
自动 kill 脚本容易踩的坑
有人写定时脚本查 TIME > 600 的 Sleep 连接然后 KILL,结果误杀正常长连接(比如报表导出、ETL 同步)。
- 不能只看
TIME,必须结合COMMAND、STATE、INFO综合判断——Sleep不等于可杀,Query也不一定危险 - 避免在业务高峰期跑 kill 脚本,尤其不要匹配
USER = 'app'这种宽泛条件 - 生产环境建议加白名单机制:只允许 kill 来自特定 host、command 为
Query且 info 包含INSERT INTO tmp_这类临时表操作的线程 - 执行前用
SELECT CONCAT('KILL ',ID,';') FROM ...生成语句,人工 review 一遍再批量执行
锁不是独立存在的,它永远绑定在某个事务生命周期里;盯着线程列表不如盯住事务状态,而事务状态又藏在 INNODB_TRX 里——这点最容易被跳过。


















