真正卡住ddl的是未提交事务持有的mdl锁;需查innodb_trx中trx_started超2分钟且trx_query为空的记录,再用sys.schema_table_lock_waits定位blocking_pid,确认其持mdl锁后执行kill释放。

真正卡住 DDL 的不是“慢查询”,而是未提交事务中挂着的 MDL 锁;KILL QUERY 无效,必须 KILL 持锁线程才能释放锁。
查 INNODB_TRX 找超时未提交的空转事务
别只看 SHOW PROCESSLIST 里 State = 'Sleep' 的连接——很多阻塞者状态是 Sleep,但实际事务仍活跃。关键指标是 trx_started 时间和 trx_query 是否为空。
- 执行:
SELECT trx_id, trx_started, trx_state, trx_mysql_thread_id, trx_query FROM information_schema.INNODB_TRX WHERE TIMESTAMPDIFF(SECOND, trx_started, NOW()) > 120; - 重点筛选:
trx_started超过 2 分钟、trx_query为空或仅含简单SELECT的记录 - 这类事务大概率是
BEGIN后忘了COMMIT或ROLLBACK,MDL 锁从开启起就一直挂着 - 注意:
trx_state = 'RUNNING'不代表正在执行语句,也可能只是事务空挂
用 sys.schema_table_lock_waits 定位等待链(MySQL 5.7+)
这是最省力的起点,一行查清谁在等、谁在堵。但前提是 sys 库可用且权限足够。
- 执行:
SELECT * FROM sys.schema_table_lock_waits\G - 关注字段:
waiting_pid(被卡住的 DDL 线程)、blocking_pid(真正持锁的线程 ID)、sql_kill_blocking_connection(可直接复制执行的KILL命令) - 如果
sys不可用或报错Access denied,立刻切到performance_schema.metadata_locks方案,别硬试 -
blocking_pid对应的线程可能在PROCESSLIST中显示为Sleep,但它的trx_started时间早于所有等待者
确认 metadata_locks 持锁类型再动手杀
盲目 KILL 可能中断正在写数据的业务事务。必须先验证该线程是否真在持 MDL 锁,且无实质修改行为。
- 查持锁记录:
SELECT OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_DURATION, LOCK_STATUS FROM performance_schema.metadata_locks WHERE OWNER_THREAD_ID = (SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = blocking_pid) AND LOCK_STATUS = 'GRANTED'; - 关键判断:
LOCK_DURATION = 'TRANSACTION'+LOCK_TYPE IN ('SHARED_READ', 'SHARED_WRITE')→ 是事务级 MDL 锁 - 再查该线程当前语句:
SELECT PROCESSLIST_INFO FROM performance_schema.threads WHERE PROCESSLIST_ID = blocking_pid;若为空或只有SELECT,基本可安全终止 - 若
PROCESSLIST_INFO显示UPDATE ... WHERE且TRX_ROWS_MODIFIED > 0,需评估回滚代价——大事务回滚本身可能卡住其他 DDL 数分钟
KILL QUERY 无效,必须用 KILL
KILL QUERY 只中断当前语句,事务仍存活,MDL 锁不会释放。DDL 会继续卡着,甚至积压更多等待者。
- 正确顺序:
KILL QUERY blocking_pid→ 等 10–20 秒 → 查PROCESSLIST看State是否变化 → 若仍是Sleep且Time持续增长,立即执行KILL blocking_pid -
KILL触发回滚,回滚时间取决于已写的 undo 日志量;提前用SHOW ENGINE INNODB STATUS\G查对应trx_id,看mysql tables in use和locked tables是否都为 0 —— 是则说明没改表结构,回滚相对快 - 注意:MySQL 8.0 默认禁止
KILL自己的连接,确保你用的是有SUPER权限的账号
最容易被忽略的一点:自动提交的 SELECT 确实会加 MDL 锁,但它在语句结束瞬间就释放了;真正危险的是显式事务里那条 SELECT 后再也没 COMMIT ——锁就挂在那儿,直到连接断开或被 KILL。











