| 引擎 | 鎖粒度 | 死鎖可能 | 適用場景 |
|---|---|---|---|
| MyISAM/MEMORY | 表鎖 | 無 | 讀多寫少、Web 應用 |
| BDB | 頁鎖/表鎖 | 有 | 較少用 |
| InnoDB | 行鎖/表鎖 | 有 | 高併發 OLTP |
表 db.tab_test:
ididx_1 (state, time)並發執行:
-- 任務 1 (掃描 idx_1 → 鎖主鍵) UPDATE tab_test SET state=1064, time=NOW() WHERE state=1061 AND time < DATE_SUB(NOW(), INTERVAL 30 MINUTE); -- 任務 2 (按主鍵 → 鎖 idx_1) UPDATE tab_test SET state=1067, time=NOW() WHERE id IN (9921180);
idx_1 範圍掃描,先鎖定 idx_1 相關記錄,再回表鎖定主鍵記錄 (Next-Key Lock 鎖住間隙)state 需同步修改 idx_1,嘗試鎖定 idx_1 記錄idx_1 等主鍵,任務 2 持有主鍵等 idx_1 → 循環等待 → 死鎖WE ROLL BACK TRANSACTION (1))-- 步驟 1:只讀查詢主鍵 (無鎖或共享鎖,極快) SELECT id FROM tab_test WHERE state=1061 AND time < DATE_SUB(NOW(), INTERVAL 30 MINUTE); -- 步驟 2:按主鍵批量更新 (主鍵點查,無範圍掃描,無 Next-Key Lock) UPDATE tab_test SET state=1064, time=NOW() WHERE id IN (上一步查出的 id 列表);
innodb_lock_wait_timeout (預設 50s) 避免無限等待innodb_print_all_deadlocks=ON (5.6.2+) 記錄完整死鎖日誌