| 儲存引擎 | 鎖粒度 | 死鎖風險 | 特點 |
|---|---|---|---|
| MyISAM / MEMORY / ISAM | 表鎖 | 無 (死鎖免疫) | 讀讀共存、讀寫互斥、寫寫互斥 |
| BDB (BerkeleyDB) | 頁鎖 | 有 | 頁面級並發,SQL 執行時獲取鎖 |
| InnoDB | 行鎖 | 有 | 索引條件下行鎖,事務開始不鎖,執行時才鎖 |
核心原則:沒有絕對最好的鎖,只有最適合應用存取模式的鎖。Web 應用多讀少寫、索引更新、追加寫入 → MyISAM 極佳;高併發寫入、事務需求 → InnoDB 必選。
鎖釋放時,寫鎖佇列優先獲得鎖,讀鎖佇列必須等所有寫鎖完成。意味著:大量更新操作會導致 SELECT 長時間等待。
SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 1151552 | -- 立即獲得
| Table_locks_waited | 15324 | -- 等待過
+-----------------------+---------+
Table_locks_waited / Table_locks_immediate > 1% 即需關注優化。
-- 使用暫存表批次轉移
LOCK TABLES real_table WRITE, insert_table WRITE;
INSERT INTO real_table SELECT * FROM insert_table;
TRUNCATE TABLE insert_table;
UNLOCK TABLES;
WHERE pk=val)「按需複製」/「寫時複製」:讀取不加鎖,讀到一致性快照;寫入建立新版本。優點:讀寫不阻塞。缺點:最壞情況記憶體佔用更高。
SELECT GET_LOCK('my_lock', 10); -- 獲取命名鎖,最多等 10 秒
-- 業務邏輯
SELECT RELEASE_LOCK('my_lock'); -- 釋放
僅適用於可信任應用程式 (勸告鎖,不強制),適合分散式協調、單機序列化。
SQL_BUFFER_RESULT 將結果集寫入暫存表,快速釋放表鎖--low-priority-updates:降低寫入優先級,SELECT 優先SET LOW_PRIORITY_UPDATES=1INSERT LOW_PRIORITY ...、SELECT HIGH_PRIORITY ...max_write_lock_count:寫鎖達閾值後暫時提升讀優先級INSERT DELAYED (MyISAM) 或批次處理DELETE ... LIMIT n 分批刪除修改 mysys/thr_lock.c 合併讀寫鎖佇列,讓優先級平等。僅建議極度熟悉 MySQL 內核的團隊嘗試。
| 現象 | 可能原因 | 排查指令 |
|---|---|---|
| SELECT 突然變慢 | 長時間 UPDATE 阻塞 | SHOW PROCESSLIST、SHOW ENGINE INNODB STATUS |
| 死鎖頻發 | InnoDB 多事務交叉鎖定 | SHOW ENGINE INNODB STATUS 看 LATEST DEADLOCK |
| 寫入吞吐低 | 表鎖競爭、索引過多 | SHOW STATUS LIKE 'Table_locks%' |
| 磁碟 IOPS 滿載 | 大事務、無索引 UPDATE | iostat -x 1、慢查詢日誌 |
Table_locks_waited、InnoDB 行鎖等待LOW_PRIORITY_UPDATES 等參數 (緩解)鎖不是調校參數,而是架構決策的體現。理解業務模式,選對引擎,優化查詢,才是解決鎖爭用的正道。