SHOW FULL PROCESSLIST 可准确识别慢DDL线程:需用 FULL 避免Info截断,过滤 Command='Query' 且 State 含 altering table/creating/Waiting for table metadata lock,并检查 Info 是否以 ALTER/CREATE/DROP 开头;KILL QUERY 对DDL无效,必须用 KILL CONNECTION 强制回滚释放MDL锁,但回滚本身可能耗时较长。

如何用 SHOW FULL PROCESSLIST 准确识别慢DDL线程
DDL(如 ALTER TABLE、CREATE INDEX)一旦开始执行,往往长时间卡在 State: Waiting for table metadata lock 或 State: altering table,但默认 SHOW PROCESSLIST 会截断 Info 列,根本看不到是不是 DDL。必须加 FULL:
SHOW FULL PROCESSLIST
重点过滤:Command = 'Query' 且 State 包含 altering、creating、Waiting for table metadata lock;同时检查 Info 是否以 ALTER、CREATE、DROP 开头。注意:MySQL 8.0+ 中 DDL 默认走原子 DDL 日志,但大表操作仍可能阻塞数分钟甚至更久。
为什么 KILL QUERY 对大多数 DDL 无效,必须用 KILL CONNECTION
MySQL 内部对 DDL 的执行有特殊保护机制:KILL QUERY 发送后,线程状态可能短暂变为 Killed,但实际不会中断 DDL 流程——它会被忽略或延迟到下一个可中断点(比如完成当前页扫描),而这个“点”可能永远不出现。真实场景中,KILL QUERY 后 State 仍显示 altering table 且 Time 持续上涨,就是典型无效信号。此时唯一可靠方式是:KILL CONNECTION <code>id。它强制关闭连接,触发 InnoDB 回滚整个 DDL 事务(包括已写入的临时文件和日志),释放 MDL 锁。但要注意:DDL 回滚本身也可能耗时很长(尤其已处理过半的大表)。
避免误杀等待者:区分「DDL 持有者」和「被堵住的 SELECT/UPDATE」
一个常见陷阱是看到一堆 State: Waiting for table metadata lock 就批量 KILL,结果全杀了等待者,真正的 DDL 线程却漏掉了。正确做法是:
- 先查出所有
State含metadata lock的线程,记下它们的Info(通常是普通查询)和ID - 再单独执行
SELECT * FROM information_schema.PROCESSLIST WHERE Info LIKE '%ALTER%' OR Info LIKE '%CREATE%';,定位那个State是altering table或preparing的线程 - 对比两者
DB和Info中的表名——等待者的Info表名,一定和持有者的 DDL 目标表一致 - 只
KILL CONNECTION那个真正执行 DDL 的ID,其余等待者会自动解除阻塞
KILL CONNECTION 后状态仍为 Killed 是正常现象
执行 KILL CONNECTION <code>id 后立刻查 PROCESSLIST,如果看到该线程 Command 变成 Connect 或消失,说明成功;但如果还存在且 State = 'Killed',不要重复执行 KILL。这是因为:
- InnoDB 正在回滚 DDL 创建的中间状态(如临时 .ibd 文件、DDL 日志条目)
- 回滚时间与已处理的数据量正相关,可能长达数分钟
- 期间线程不可中断,
SHOW PROCESSLIST无法反映内部进度 - 可通过
SELECT * FROM performance_schema.events_statements_current WHERE THREAD_ID = <code>thread_id;(MySQL 8.0+)确认是否仍在清理
Killed 且 Time 不变——这可能意味着回滚卡死,需结合错误日志排查存储引擎层异常。


















