| 維度 | READ COMMITTED (RC) | REPEATABLE READ (RR, 預設) |
|---|---|---|
| Gap Lock / Next-Key Lock | ❌ 無 | ✅ 有 (防幻讀) |
| 不符合 WHERE 條件行鎖 | 掃描後**即時釋放** (違反 2PL) | **保持持有** 至事務結束 |
| Binlog 格式支援 | 僅 ROW / MIXED (Statement 導致不一致) | 支援 Statement / ROW / MIXED |
| ReadView 生成時機 | **每條 SELECT** 獨立生成 | **首條 SELECT** 生成,全事務共用 |
| 一致性讀語義 | 讀到執行時已提交數據 | 讀到事務啟動快照數據 |
| UPDATE 半一致性讀 | ✅ 支援 (Semi-Consistent Read) | ❌ 不支援 (當前讀直接等鎖) |
| 並發寫入性能 | 優 (鎖釋放激進、半一致性讀) | 較低 (Gap Lock、持有鎖久) |
| 應用場景 | 高併發 OLTP、現代 ROW 架構 | 傳統事務密集、依賴可重複讀語義 |
SELECT ... FOR UPDATE、UPDATE、DELETE 走索引時加 Next-Key Lock (Record+Gap),鎖定區間 (prev, curr],阻塞插入。WHERE 過濾後不符合條件的行,行鎖**即時釋放** (InnoDB 內部優化,違反嚴格兩階段鎖協議)。RR 則**全程持有**。NOW()、UUID()) + RC 可見性差異 → 主從數據不一致。SELECT 執行瞬間創建 ReadView,見該時刻已提交數據。**同一事務兩次 SELECT 可見不同版本** (不可重複讀)。SELECT 創建 ReadView,後續所有查詢共用。**同一事務多次 SELECT 見相同版本** (可重複讀)。m_ids (活躍事務 ID 列表)、min_trx_id、max_trx_id。可見性判斷:trx_id < min_trx_id 可見;>= max_trx_id 不可見;在列表中 不可見 (未提交);不在列表中 可見 (已提交)。觸發條件:RC 隔離級別 + UPDATE 掃描到**已加鎖記錄**。
流程:
WHERE 條件是否滿足。對比 RR:RR 下 UPDATE 直接當前讀,遇鎖**阻塞等待**,不進行條件預判。
收益:批量更新大量不符合條件行時,RC 大幅減少鎖等待、死鎖概率。
| 隔離級別 | 標準要求防止 | MySQL 實際防止 |
|---|---|---|
| READ UNCOMMITTED | 無 | 無 |
| READ COMMITTED | 髒讀 | 髒讀 |
| REPEATABLE READ | 髒讀、不可重複讀 | 髒讀、不可重複讀、**幻讀** (Gap Lock) |
| SERIALIZABLE | 髒讀、不可重複讀、幻讀 | 髒讀、不可重複讀、幻讀 (全加鎖) |
MySQL RR **超標準實現**了防幻讀,這是其選為預設的核心原因之一。
RC 與 RR 的本質差異在於 **「鎖的激進程度」與「快照的生命週期」**。RC 通過釋放無效鎖、半一致性讀優化更新路徑,適應現代高吞吐場景;RR 通過統一事務級快照、Gap Lock 防幻讀,提供更強一致性保證。理解機制,方能根據業務特性在一致性與性能間做最優權衡。