Metadata lock阻塞源是未提交事务,需重点排查Sleep状态且TIME>300秒的幽灵连接及INNODB_TRX中RUNNING且trx_started过早的事务,结合SHOW ENGINE INNODB STATUS验证是否无表操作后谨慎KILL。

查哪些线程在持锁不放
Metadata lock wait 的本质是:有事务(哪怕只执行了 BEGIN)没提交,后续的 ALTER TABLE、DROP INDEX 等 DDL 就会卡在 Waiting for table metadata lock 状态。关键不是“谁在等”,而是“谁在占”。
先看活跃连接里谁在空耗时间:
-
SHOW PROCESSLIST中STATE为Waiting for table metadata lock的线程,是受害者,不是元凶 - 真正要盯的是
COMMAND = 'Sleep'但TIME > 300且INFO为空的线程——这极大概率是应用异常断开后留下的“幽灵事务” - 再结合
INFORMATION_SCHEMA.INNODB_TRX查trx_state = 'RUNNING'且trx_started时间远早于当前时间的记录
这两类线程的 trx_mysql_thread_id 或 ID 就是待 Kill 的目标。
Kill 前必须确认它真没干活
直接 KILL 风险很高,尤其在生产环境。不能只看 TIME 大就动手。
安全判断步骤:
- 用
SHOW ENGINE INNODB STATUS\G查TRANSACTIONS部分,找到对应trx_id,看mysql tables in use和locked tables是否都为 0 —— 是,则基本没实际操作,可 Kill - 检查
PROCESSLIST中该线程的STATE:若为Starting authentication或长期Waiting for table metadata lock,大概率已僵死;若为executing或sending data,需谨慎 - 优先执行
KILL QUERY(只中断当前语句),观察是否释放 MDL;若无效,再KILL
MySQL 8.0 下特别注意隔离级别和锁生命周期
在 REPEATABLE READ 隔离级别下,MDL 锁从 BEGIN 就持有,不是等到第一次 SELECT 才加。这意味着一个空事务 BEGIN; -- 没有后续语句 也能阻塞 DDL。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
常见误判点:
-
trx_query为空 ≠ 没持锁;trx_state = 'RUNNING'且trx_isolation_level = 'REPEATABLE READ'就足以构成阻塞源 - MySQL 8.0 默认
wait_timeout = 28800(8 小时),对连接池场景太宽松,未提交事务可能挂数小时而不被自动断开 - 升级后务必检查并收紧:
SET GLOBAL wait_timeout = 300、SET GLOBAL interactive_timeout = 300
自动化定位阻塞源头的 SQL 要慎用
网上流传的“一键 Kill 所有长事务”脚本(比如拼接 KILL 语句的子查询)容易误杀。真实环境里,阻塞源往往不是最老的事务,而是某个刚执行完慢查询、正卡在 commit 阶段的连接。
更稳妥的做法是分步手动确认:
- 先运行
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_started - 对结果中的每个
trx_mysql_thread_id,执行SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = ?;看状态 - 再执行
SHOW ENGINE INNODB STATUS\G定位具体锁信息,交叉验证
复杂点在于:MDL 锁不体现在 INNODB_LOCKS 里,它独立于行锁/表锁机制,所以不能依赖 INNODB_LOCK_WAITS 反向找 blocking_trx_id——这个字段在 MDL 场景下无意义。










