MDL 堵表时,用 metadata_locks 找出元凶
场景:A 开着事务不提交,B 的 ALTER 在等,C 这些查询排在 B 后面。
只看 SHOW PROCESSLIST 找不到 A:它的 Command 是 Sleep、Info 是空的,看起来就是个空闲连接。要查 MDL 的持有情况:
SELECT m.LOCK_TYPE, m.LOCK_STATUS, t.PROCESSLIST_ID, t.PROCESSLIST_COMMAND
FROM performance_schema.metadata_locks m
JOIN performance_schema.threads t ON t.THREAD_ID = m.OWNER_THREAD_ID
WHERE m.OBJECT_SCHEMA = 'lab' AND m.OBJECT_NAME = 'cfg';我本地复现时的输出(A 是一个开了事务、读完就闲着的连接):
LOCK_TYPE LOCK_STATUS ID COMMAND
SHARED_READ GRANTED 41 Sleep ← A:拿着读锁
SHARED_UPGRADABLE GRANTED 42 Query ← B:ALTER 先拿 SU
EXCLUSIVE PENDING 42 Query ← B:在等写锁
SHARED_READ PENDING 43 Query ← C:排在 B 后面认法:同时持有 SU、又在等 EXCLUSIVE 的是 ALTER;GRANTED 的读锁、线程在 Sleep 的是元凶。
5.7 要先打开 MDL 的记录开关(setup_instruments 里的 wait/lock/metadata/sql/mdl),开之前拿的锁记不到;8.0 起默认开。