InnoDB 通過 MVCC(多版本併發控制)與鎖機制實現 ACID 特性,四大隔離級別在鎖行為與一致性讀上差異顯著。
事務 ACID 四特性
| 特性 | 含義 |
| 原子性 | 事務內操作全做或全不做 |
| 一致性 | 事務前後數據庫處於一致狀態 |
| 隔離性 | 併發事務互不干擾 |
| 持久性 | 提交後修改永久生效,抗崩潰 |
四大隔離級別與鎖行為對比
| 隔離級別 | 髒讀 | 不可重複讀 | 幻讀 | 默認 SELECT 鎖行為 |
| READ UNCOMMITTED | ✅ 可能 | ✅ 可能 | ✅ 可能 | 無鎖 |
| READ COMMITTED | ❌ | ✅ 可能 | ✅ 可能 | 無鎖 |
| REPEATABLE READ | ❌ | ❌ | ❌ (間隙鎖防禦) | 無鎖 (MVCC 快照讀) |
| SERIALIZABLE | ❌ | ❌ | ❌ | 隱式 LOCK IN SHARE MODE |
InnoDB 核心鎖類型
LOCK IN SHARE MODE:共享鎖(S 鎖),讀取加鎖,阻塞寫入。
FOR UPDATE:排他鎖(X 鎖),讀取加鎖,阻塞讀寫。
INSERT/UPDATE/DELETE:隱式排他鎖(X 鎖)。
- 間隙鎖 / Next-Key Lock:鎖定索引區間,防止幻讀(RR 級別生效)。
實戰驗證矩陣(節選)
環境:SET GLOBAL tx_isolation='REPEATABLE-READ',表 account(id PK, vaccount_id, gmt_create),10 萬行測試數據。
| 步驟 | 事務 1 | 事務 2 | 現象 |
| 1 | START TRANSACTION | | |
| 2 | SELECT vaccount_id WHERE id=1001 → 'caimao101510' | | |
| 3 | | START TRANSACTION | |
| 4 | | UPDATE ... SET vaccount_id='uncommitted' WHERE id=1001 | X 鎖持有 |
| 5 | | SELECT ... → 'uncommitted' | 事務 2 可見自身修改 |
| 6 | SELECT ... → 'caimao101510' | | **RR 級別:可重複讀,不可見他事務未提交修改** |
| 7 | | COMMIT | |
| 8 | SELECT ... → 'caimao101510' | | 仍見舊值(快照讀) |
| 9 | COMMIT | | |
關鍵現象總結
- RR 級別:普通 SELECT 為快照讀(無鎖),
FOR UPDATE/LOCK IN SHARE MODE 為當前讀(加鎖)。
- 間隙鎖觸發:
WHERE id >= 124999 範圍更新會鎖定 (124999, +∞) 區間,阻塞該區間內插入。
- 無索引更新:
WHERE gmt_create > '2009-07-01' 全表掃描加鎖,阻塞全表插入,極大降低併發。
最佳實踐
- 默認使用
REPEATABLE READ,平衡一致性與併發。
- 所有更新/刪除**必須走索引**,避免全表鎖。
- 長事務拆分,縮短鎖持有時間。
- 熱點行更新採用樂觀鎖(版本號)減少衝突。