鎖是資料庫並發控制的核心。MySQL 不同儲存引擎支援不同粒度的鎖:MyISAM/MEMORY 用表鎖,BDB 用頁鎖,InnoDB 用行鎖。本文系統分析三種鎖級別特性、加鎖規則、死鎖成因與實戰優化策略。
| 維度 | 表鎖 | 頁鎖 | 行鎖 |
|---|---|---|---|
| 典型引擎 | MyISAM, MEMORY, CSV | BDB | InnoDB |
| 鎖定粒度 | 整張表 | 一頁(通常 16KB) | 單行記錄 |
| 並發效能 | 低(讀寫互斥) | 中 | 高(細粒度) |
| 記憶體開銷 | 極小 | 中等 | 大(每行鎖結構) |
| 死鎖可能 | 無(一次性獲取所有鎖) | 有 | 有 |
| 適用場景 | 唯讀、全表掃描、批量載入 | 較少用 | 高併發 OLTP、頻繁點查/更新 |
SELECT ... LOCK IN SHARE MODE,兼容 S 鎖,阻塞 X 鎖。SELECT ... FOR UPDATE、UPDATE、DELETE、INSERT,阻塞 S/X 鎖。(前值, 當前值]。-- 寫鎖 (WRITE LOCK)
LOCK TABLES tbl_name WRITE;
-- 讀鎖 (READ LOCK)
LOCK TABLES tbl_name READ;
-- 解鎖
UNLOCK TABLES;
隊列規則:
可用 LOW_PRIORITY WRITE、HIGH_PRIORITY READ 調整優先級。
-- Session A -- Session B
BEGIN; BEGIN;
UPDATE t SET v=1 WHERE id=1; UPDATE t SET v=2 WHERE id=2;
UPDATE t SET v=3 WHERE id=2; (阻塞) UPDATE t SET v=4 WHERE id=1; (死鎖)
COMMIT; COMMIT;
InnoDB 自動檢測死鎖並回滾代價較小的事務(通常是更新行數少者)。
SHOW ENGINE INNODB STATUS\G 查看 LATEST DETECTED DEADLOCK 區塊。INSERT ... ON DUPLICATE KEY UPDATE 替代「先查後插/更新」模式,減少間隙鎖。concurrent_insert=2;InnoDB 自動支援尾部並發插入。innodb_lock_wait_timeout=50(預設 50s),防止長時間阻塞拖垮連接池。Innodb_row_lock_waits、Innodb_row_lock_time_avg、Innodb_deadlocks。$db->execute("LOCK TABLES stat_num WRITE");
$db->execute("UPDATE stat_num SET correct_num = correct_num + 1 WHERE stat_date = '{$cur_date}'");
$db->execute("UNLOCK TABLES");
⚠️ 僅適用於 MyISAM/MEMORY 或極少數強制串行化場景。InnoDB 應改用 UPDATE ... WHERE id = ? 配合行鎖,或 SELECT ... FOR UPDATE 顯式加鎖。