首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL MVCC 多版本並發控制深度解析:原理、實現與可重複讀演示

     編輯:MySQL 綜合教學

MySQL MVCC 多版本並發控制深度解析:原理、實現與可重複讀演示

MVCC(Multi-Version Concurrency Control)是 InnoDB 實現高並發的核心技術,通過「讀不阻塞寫、寫不阻塞讀」大幅提升吞吐量。本文從底層存儲結構、版本鏈、ReadView 機制三個維度,配合具體事務演示,徹底講透 MVCC。

核心概念

  • 版本號:系統全局遞增的事務 ID(trx_id),每開啟一個事務分配一個唯一遞增 ID。
  • 隱式字段:每行記錄自帶 trx_id(創建版本)、roll_pointer(指向 Undo Log 版本鏈)、row_id(無主鍵時的隱藏主鍵)。
  • Undo Log:舊版本記錄鏈,存放於共享表空間或獨立表空間,支撐回滾與一致性讀。
  • ReadView:事務啟動時刻的「快照視圖」,包含 m_ids(活躍事務 ID 列表)、min_trx_id、max_trx_id、creator_trx_id。

版本鏈與記錄結構

+----------------+---------+----------+---------------+
| 當前記錄        | trx_id  | roll_ptr | 數據列...      |
+----------------+---------+----------+---------------+
        │
        ▼ Undo Log 鏈
+----------------+---------+----------+---------------+
| 歷史版本 1      | trx_id  | roll_ptr | 舊數據...      |
+----------------+---------+----------+---------------+
        │
        ▼
+----------------+---------+----------+---------------+
| 歷史版本 2      | trx_id  | NULL     | 更舊數據...     |
+----------------+---------+----------+---------------+

ReadView 可見性判斷規則(Repeatable Read 隔離級別)

事務讀取某版本記錄時,按順序判斷:

  1. 若 trx_id == creator_trx_id → 可見(自己修改的)。
  2. 若 trx_id < min_trx_id → 可見(事務啟動前已提交)。
  3. 若 trx_id > max_trx_id → 不可見(事務啟動後才開啟的事務)。
  4. 若 min_trx_id ≤ trx_id ≤ max_trx_id:
    • 若 trx_id IN m_ids → 不可見(活躍事務未提交)。
    • 若 trx_id NOT IN m_ids → 可見(已提交事務)。

實戰演示:四並發事務下的可重複讀

初始表 t(id PK, name, trx_id, roll_ptr),已有記錄 (1, 'a', 1, NULL)。
四事務並發(ID 分配順序):

  • T1 (trx=2):SELECT * FROM t WHERE id=1(長事務,不提交)
  • T2 (trx=3):INSERT INTO t VALUES (2, 'b')
  • T3 (trx=4):DELETE FROM t WHERE id=1
  • T4 (trx=5):UPDATE t SET name='b' WHERE id=1

T1 首次查詢:ReadView m_ids=[2,3,4,5], min=2, max=5

  • 記錄 (1,'a',trx=1) → trx_id=1 < min=2 → 可見。
  • 記錄 (2,'b',trx=3) → trx_id=3 ∈ m_ids → 不可見。
  • DELETE 標記版本 trx=4 ∈ m_ids → 原記錄 可見(未提交刪除)。
  • UPDATE 產生新版本 (1,'b',trx=5) → trx_id=5 ∈ m_ids → 不可見;舊版本 (1,'a',trx=1) 可見。
  • 結果:SELECT 返回 (1,'a')。

T1 等待 10 分鐘後再次查詢(T2/T3/T4 均未提交):ReadView 不變,結果仍為 (1,'a') → 可重複讀成立。

若 T3 提交:DELETE 版本 trx=4 變為已提交,但 T1 ReadView 中 min=2, max=5, m_ids 仍含 4 → 仍不可見。
若 T4 提交:UPDATE 版本 trx=5 已提交,同理不可見。
只有 T1 提交後,新開啟的事務才能看到最新提交版本。

Read Committed 與 Repeatable Read 的 ReadView 差異

隔離級別ReadView 創建時機效果
Read Committed每條 SELECT 執行前不可重複讀、幻讀
Repeatable Read (默認)事務首次 SELECT 前可重複讀,InnoDB 通過 Next-Key Lock 解決幻讀

MVCC 不支援的場景

  • MyISAM:無事務、無 Undo Log、表級鎖,無法實現 MVCC。
  • 鎖定讀:SELECT ... LOCK IN SHARE MODE、SELECT ... FOR UPDATE 直接加鎖,不走 MVCC。
  • DDL 操作:隱式提交,破壞事務隔離。

總結

MVCC 通過 Undo Log 版本鏈 + ReadView 可見性判斷,實現了無鎖一致性讀,是 InnoDB 高並發的基石。理解其原理,有助於排查長事務導致的 Undo Log 膨脹、History List Length 飆升、死鎖等疑難雜癥。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved