必须三表连查metadata_locks→threads→events_statements_current(或INNODB_TRX)才能准确定位MDL持锁者;因持锁线程常处Sleep状态、State和Info为空,SHOW PROCESSLIST与INNODB_TRX均无法识别,且KILL QUERY无效,须用KILL CONNECTION终止事务。

直接结论:仅查 SHOW PROCESSLIST 或 INNODB_TRX 无法定位真正的 MDL 持有者;必须三表连查 metadata_locks → threads → events_statements_current(或 INNODB_TRX),否则大概率杀错线程、延长故障。
为什么 SHOW PROCESSLIST 看不到持锁者
持锁线程常处于 Sleep 状态,State 字段为空,Info 为 NULL,但 LOCK_DURATION = 'TRANSACTION' 的 MDL 锁仍牢牢挂着——它不随语句结束释放,只随事务提交或回滚才松手。而 SHOW PROCESSLIST 只显示当前活跃状态,对这种“静默持锁”完全无感。
常见错误现象:
- 看到一堆
Waiting for table metadata lock,却找不到谁在 hold -
INNODB_TRX显示有长事务,但TRX_QUERY为空,无法确认是否锁了目标表 - 误杀等待线程,结果 DDL 依然卡住,阻塞加剧
必须启用并查询 performance_schema.metadata_locks
MySQL 8.0 默认开启该表,但需确认 instrument 已启用:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'wait/lock/metadata/sql/mdl';
关键筛选逻辑:
- 先锁定未释放的锁:
LOCK_STATUS = 'GRANTED' - 重点盯
LOCK_DURATION = 'TRANSACTION'—— 这类锁最危险,哪怕只执行过BEGIN或SELECT就断开,只要没COMMIT/ROLLBACK,锁就一直挂着 - 结合目标库表过滤:
OBJECT_SCHEMA = 'your_db'且OBJECT_NAME = 'your_table'
单表查只能看到锁存在,看不到是谁持的——因为 OWNER_THREAD_ID 是内部线程 ID,不是 PROCESSLIST_ID。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
必须通过 threads 表做 THREAD_ID → PROCESSLIST_ID 映射
PROCESSLIST_ID 不等于 THREAD_ID,跳过 threads 表直接 KILL 会杀错连接。正确连查如下:
SELECT m.OBJECT_SCHEMA, m.OBJECT_NAME, m.LOCK_TYPE, t.PROCESSLIST_ID, t.PROCESSLIST_INFO FROM performance_schema.metadata_locks m JOIN performance_schema.threads t ON m.OWNER_THREAD_ID = t.THREAD_ID WHERE m.LOCK_STATUS = 'GRANTED' AND m.LOCK_DURATION = 'TRANSACTION' AND t.TYPE = 'FOREGROUND' AND m.OBJECT_SCHEMA = 'your_db' AND m.OBJECT_NAME = 'your_table';
注意点:
-
t.TYPE = 'FOREGROUND'排除后台线程(如复制 IO/SQL 线程) - 若
PROCESSLIST_INFO为空,别慌——这是常态,说明语句已执行完,但事务没结束 - 拿到
PROCESSLIST_ID后,务必再交叉验证:SELECT * FROM information_schema.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = ?
KILL CONNECTION 才是唯一有效动作
KILL QUERY 对 Sleep 中的持锁事务完全无效,它只中断当前语句,事务仍在运行,MDL 锁纹丝不动。
必须执行:
KILL CONNECTION <code>id</code>;
而不是 KILL QUERY <code>id。但要注意:
- 如果该连接被连接池复用,强制断连可能触发重连风暴,建议配合应用侧临时降级
- 若事务已写入大量数据,回滚本身可能耗时数分钟,期间仍阻塞其他 DDL
- 某些 ORM(如 Hibernate)在异常断连后可能残留事务状态,后续请求易出错
真正容易被忽略的是:metadata_locks 中的 LOCK_TYPE 值(如 SHARED_WRITE、EXCLUSIVE)决定了影响范围——EXCLUSIVE 锁住所有读写,SHARED_WRITE 则允许普通 SELECT,但会阻塞 DDL 和写锁升级。不看这个字段,就无法判断阻塞严重程度。

















