查不到mdl锁因performance_schema.metadata_locks默认关闭:5.7需手动启用wait/lock/metadata/sql/mdl,8.0起默认开启;exclusive锁才是写锁,shared_upgradable不是。

直接看 performance_schema.metadata_locks 表,但必须先打开它——否则查不到任何 MDL 锁信息。
为什么查不到 MDL 锁?因为默认关闭
MySQL 5.7 中 performance_schema.metadata_locks 表存在但默认禁用;8.0 起才默认开启。如果执行 SELECT * FROM performance_schema.metadata_locks 返回空,大概率是没开采集:
- 检查是否启用:
SELECT * FROM performance_schema.setup_instruments WHERE NAME = 'wait/lock/metadata/sql/mdl'; - 若
ENABLED列为NO,需手动开启:UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'wait/lock/metadata/sql/mdl'; - 该设置只对新连接生效,已有连接不会补录历史锁
如何识别当前事务持有的 MDL 写锁
MDL 写锁对应 LOCK_TYPE = 'EXCLUSIVE'(即 X 锁),常见于 ALTER TABLE、DROP TABLE、RENAME TABLE 等 DDL 操作。关键字段组合判断:
-
OBJECT_TYPE = 'TABLE'且LOCK_TYPE = 'EXCLUSIVE'→ 明确是表级写锁 -
OWNER_THREAD_ID关联performance_schema.threads可查到具体会话和 SQL -
LOCK_STATUS = 'GRANTED'表示已持有(不是等待中) - 注意:
LOCK_DURATION = 'TRANSACTION'表示该锁会持续到事务提交或回滚
示例查询:
SELECT m.OBJECT_SCHEMA, m.OBJECT_NAME, m.LOCK_TYPE, m.LOCK_DURATION, m.LOCK_STATUS, t.PROCESSLIST_INFO AS SQL_TEXT FROM performance_schema.metadata_locks m JOIN performance_schema.threads t ON m.OWNER_THREAD_ID = t.THREAD_ID WHERE m.LOCK_TYPE = 'EXCLUSIVE' AND m.LOCK_STATUS = 'GRANTED';
容易误判的点:SHARED_UPGRADABLE 不是写锁
看到 LOCK_TYPE = 'SHARED_UPGRADABLE'(SU)别急着当成写锁——它只是“可升级”,实际仍属读锁范畴,常出现在 SELECT ... FOR UPDATE 或某些 DML 开始阶段,不阻塞其他 DML,只阻塞后续 DDL。真正互斥的是 EXCLUSIVE 锁。
另外,LOCK_MODE 字段在 5.7 中不存在,8.0+ 才有,不要依赖它做判断;LOCK_TYPE 和 LOCK_STATUS 才是核心依据。
最常被忽略的是:即使事务里只执行了一条 SELECT,只要没提交,它就一直持有一个 SHARED_READ 锁——这本身不阻塞 DDL,但一旦有人在它之后发起 ALTER TABLE,那个 ALTER 就会卡住,而你查 metadata_locks 时可能只盯着 EXCLUSIVE,却忘了去看谁在“挡路”。











