Metadata Lock (MDL) 是 MySQL 5.5+ 引入的元數據鎖,保護表結構定義(Schema)在併發 DDL/DML 下不被破壞。本文深度解析 MDL 來源、鎖類型、兼容性矩陣、典型死鎖場景、監控排查命令、MySQL 8.0 優化新特性(原子 DDL、MDL 粒度細化)。
| 鎖類型 | 代碼 | 持有者 | 兼容性 |
| 共享讀 | MDL_SHARED_READ | SELECT、INSERT/UPDATE/DELETE(讀取表結構) | 兼容 S、SH、SW,不兼容 X |
| 共享寫 | MDL_SHARED_WRITE | INSERT/UPDATE/DELETE(修改數據) | 兼容 S,不兼容 SH、SW、X |
| 共享高優先級寫 | MDL_SHARED_WRITE_HIGH_PRIO | REPLACE、LOAD DATA | 兼容 S,不兼容 SH、SW、X |
| 排他 | MDL_EXCLUSIVE | ALTER/DROP/TRUNCATE/RENAME/OPTIMIZE | 不兼容任何其他 |
| 意向排他 | MDL_INTENTION_EXCLUSIVE | CREATE TABLE、CREATE INDEX(5.6+ Online DDL 階段) | 兼容 S,不兼容 SH、SW、X、IX |
三、典型死鎖/阻塞場景
1. 長事務阻塞 DDL(最常見)
-- Session A
BEGIN;
SELECT * FROM t WHERE id=1 FOR UPDATE; -- 持有 S 鎖
-- 忘記 COMMIT,去喝咖啡了...
-- Session B
ALTER TABLE t ADD COLUMN c INT; -- 等待 X 鎖,阻塞
-- 所有後續 SELECT/INSERT 也排隊等待 S 鎖(被 B 的 X 鎖請求阻塞)
現象:`SHOW PROCESSLIST` 大量 `Waiting for table metadata lock`。
2. 併發 DDL 互相等待
-- Session A
ALTER TABLE t1 ADD COLUMN a INT; -- 持有 t1 X 鎖
ALTER TABLE t2 ADD COLUMN b INT; -- 等待 t2 X 鎖
-- Session B
ALTER TABLE t2 ADD COLUMN c INT; -- 持有 t2 X 鎖
ALTER TABLE t1 ADD COLUMN d INT; -- 等待 t1 X 鎖
-- 死鎖(MySQL 會自動檢測並回滾一方)
3. 外鍵檢查引發的隱式 MDL
INSERT INTO child ... 需讀取父表結構 → 持有父表 S 鎖。若同時對父表 ALTER,將阻塞。
四、監控與排查命令
-- 1. 查看當前 MDL 等待(5.7+ performance_schema)
SELECT * FROM performance_schema.metadata_locks
WHERE LOCK_STATUS = 'PENDING';
-- 2. 關聯線程
SELECT * FROM performance_schema.metadata_locks ml
JOIN performance_schema.threads t ON ml.OWNER_THREAD_ID = t.THREAD_ID
WHERE ml.LOCK_STATUS = 'PENDING';
-- 3. 簡易版:SHOW PROCESSLIST 看 State
SHOW PROCESSLIST;
-- State: "Waiting for table metadata lock" 即為 MDL 等待
-- 4. 查找長事務(阻塞 DDL 根因)
SELECT * FROM information_schema.INNODB_TRX
WHERE TRX_STARTED < NOW() - INTERVAL 60 SECOND;
五、MySQL 8.0 優化新特性
- 原子 DDL:
ALTER TABLE、DROP TABLE、CREATE INDEX 等元數據操作寫入單一事務,Crash 後自動回滾或提交,無中間狀態。
- MDL 粒度細化:分區表 DDL 僅鎖定涉及分區,而非整表;瞬間加列(Instant ADD COLUMN)無需複製表,**無 MDL X 鎖**,僅需瞬間 S 鎖升級。
- DDL 階段鎖降級:Online DDL 準備階段持有 IX,執行階段短暫升 X,提交前降回 S,大幅縮短阻塞窗口。
- performance_schema 增強:`metadata_locks` 表新增 `LOCK_DURATION`(STATEMENT/TRANSACTION/EXPLICIT),便於精準定位持鎖範圍。
六、運維預防清單
- **嚴禁長事務**:應用層設置事務超時(如 Spring `@Transactional(timeout=30)`),監控 `INNODB_TRX` 超過 60 秒告警。
- **DDL 低峰執行**:配合 `pt-online-schema-change`/`gh-ost` 在線變更,避免原生 DDL 長鎖。
- **監控 MDL 等待**:Prometheus 抓取 `performance_schema.metadata_locks`,`LOCK_STATUS='PENDING'` 持續 > 5 秒告警。
- **避免併發 DDL 同表**:運行維窗口串行執行,或使用工具隊列化。
MDL 是「守護 Schema 一致性」的隱形衛士,理解其機制、監控其等待、消除長事務,是高併發 MySQL 穩定運行的必修課。
- 上一篇文章: MySQL SQL Mode 完整指南:模式分類、ANSI/嚴格/傳統模式差異、異構遷移組合、數據驗證功能與生產配置建議
- 下一篇文章: MySQL Online DDL 原理與演進:從 5.5 FIC 到 5.6 在線結構變更
Copyright ©
程式碼之家 All Rights Reserved