鎖是資料庫並發控制的核心。MySQL 採用插件式存儲引擎架構,鎖實現下推至引擎層:**MyISAM 表級鎖**、**InnoDB 行級鎖**(含意向鎖、間隙鎖、Next-Key Lock)。本文系統對比兩大引擎鎖特性、演示實戰場景、給出生產級調優建議。全文約 6000 字,建議收藏細讀。
| 維度 | 表級鎖 | 頁級鎖 | 行級鎖 |
|---|---|---|---|
| 典型引擎 | MyISAM, MEMORY, CSV | BerkeleyDB | InnoDB, NDB Cluster |
| 粒度 | 整張表 | 頁(通常 16KB) | 單行記錄 |
| 並發度 | 低 | 中 | 高 |
| 鎖開銷 | 最小 | 中等 | 最大 |
| 死鎖風險 | 無 | 有 | 有 |
| 實現複雜度 | 簡單 | 中等 | 複雜 |
Current read-lock queue:持有讀鎖線程(按獲取時間序)。Pending read-lock queue:等待讀鎖線程。Current write-lock queue:持有寫鎖線程。Pending write-lock queue:等待寫鎖線程。除常見 READ/WRITE 外,關鍵特殊類型:
READ_NO_INSERT:禁止 Concurrent Insert。WRITE_CONCURRENT_INSERT:允許尾部並發插入。WRITE_ALLOW_READ:DDL 重建表階段,允許讀舊表。WRITE_DELAYED:INSERT DELAYED 專用。READ_HIGH_PRIORITY:高優先級讀(HIGH_PRIORITY hint)。Pending write 阻塞後續所有讀請求。LOW_PRIORITY_UPDATES=1 可反轉優先級,適合讀多寫少場景。concurrent_insert=2:無論中間有無空洞,允許尾部插入。=1(預設):無空洞才允許尾部插入。=0:禁用。| S (共享) | X (排他) | IS (意向共享) | IX (意向排他) | |
|---|---|---|---|---|
| S | 兼容 | 衝突 | 兼容 | 衝突 |
| X | 衝突 | 衝突 | 衝突 | 衝突 |
| IS | 兼容 | 衝突 | 兼容 | 兼容 |
| IX | 衝突 | 衝突 | 兼容 | 兼容 |
(前一鍵值, 當前鍵值](左開右閉)。WHERE 無索引 → 全表掃描 → 加表級 X 鎖,並發度歸零。WHERE a=1 AND b='x' vs WHERE a=1 AND b='y',若只走 idx_a,兩事務互鎖。| 場景 | 現象 | 根因 |
|---|---|---|
| 基本行鎖阻塞 | Session A 未提交 UPDATE,Session B 同行 UPDATE 阻塞 | X 鎖衝突 |
| 無索引升級表鎖 | Session A UPDATE 無索引列,Session B UPDATE 另一無索引列阻塞 | 全表 X 鎖 |
| 間隙鎖阻塞插入 | Session A UPDATE ... WHERE a<4 AND a>1,Session B INSERT a=2 阻塞 | Next-Key Lock 鎖住 (1,4] 間隙 |
| 相同索引不同值阻塞 | Session A UPDATE ... a=1 AND b='b2',Session B UPDATE ... a=1 AND b='b1' 阻塞 | 共用 idx_a,間隙鎖重疊 |
| 死鎖 | Session A 鎖 t1 再鎖 t2,Session B 鎖 t2 再鎖 t1 | 循環等待,InnoDB 自動檢測回滾小事務 |
READ UNCOMMITTED:不加 S 鎖,可能髒讀。READ COMMITTED:無間隙鎖,僅鎖定存在的索引記錄(RC 下半一致性讀)。REPEATABLE READ(預設):**有間隙鎖**,防止幻讀。SERIALIZABLE:讀隱式加 S 鎖,等同表級共享鎖。innodb_lock_wait_timeout(預設 50s)超時回滾。SHOW ENGINE INNODB STATUS 可見最新死鎖詳情(LATEST DETECTED DEADLOCK)。OPTIMIZE TABLE。concurrent_insert=2,讓讀寫並行。low_priority_updates=1,提升讀優先級。<, >, BETWEEN, LIKE '%...'),降低間隙鎖影響。LOCK TABLES)。-- 表鎖
SHOW STATUS LIKE 'Table_locks%';
Table_locks_immediate: 立即獲取次數
Table_locks_waited: 等待次數(此值高需優化)
-- 行鎖
SHOW STATUS LIKE 'Innodb_row_lock%';
Innodb_row_lock_waits: 總等待次數
Innodb_row_lock_time_avg: 平均等待毫秒
Innodb_row_lock_time_max: 最大等待毫秒
Innodb_row_lock_time: 總等待毫秒
-- 詳細即時資訊
CREATE TABLE innodb_monitor (a INT) ENGINE=InnoDB; -- 開啟監控
SHOW ENGINE INNODB STATUS\G -- 查看事務、鎖、等待圖
MyISAM 表鎖簡單低開銷但並發低;InnoDB 行鎖並發高但複雜、有間隙鎖副作用。生產環境**核心業務務必用 InnoDB**,並遵循「索引覆蓋、事務精簡、隔離級別適配、訪問順序固定」四大原則,將鎖爭用壓制在可接受水平。