動態

詳情 返回 返回

MVCC(多版本併發控制)底層原理 - 動態 詳情

MVCC(多版本併發控制)底層原理總結:

MVCC 是通過維護數據的多個版本來控制併發訪問的技術,它使得數據庫能夠支持高併發事務,同時保證事務之間的隔離性和一致性。在 MySQL 的 InnoDB 存儲引擎中,MVCC 是通過 隱藏列ReadView 快照undo log 來實現的。

1. 關鍵概念:

  • 隱藏列(Hidden Columns):為了支持 MVCC 機制,InnoDB 在每一行數據中隱藏了兩個額外的列,分別是 DB_TRX_IDDB_ROLL_PTR。這兩個列並不直接暴露給用户,但它們對 MVCC 的工作至關重要。DB_TRX_ID 存儲了最近修改該行數據的事務 ID,而 DB_ROLL_PTR 存儲了指向該行數據歷史版本的指針。
  • ReadView 快照:為了支持事務隔離級別(如“讀已提交”或“可重複讀”),InnoDB 會在每個查詢操作時創建一個 ReadView 快照。該快照存儲了當前查詢事務的 ID、所有未提交事務的事務 ID(按升序排列)以及未開始的事務 ID。通過這些信息,數據庫可以判斷查詢事務能看到哪些數據版本。
  • Undo Log(回滾日誌):記錄事務對數據的修改操作。當事務修改數據時,InnoDB 會為該數據生成一個新的版本,舊版本數據會保存在 undo log 中。

2. ReadView 快照內容:

  • 當前查詢事務 ID:表示當前正在執行查詢的事務 ID。
  • 未提交事務的事務 ID(按升序排列):記錄了當前未提交事務的事務 ID,從最小到最大排序。
  • 未開始的事務 ID:記錄那些尚未開始的事務 ID。

3. Undo Log 數據讀取邏輯:

當執行查詢操作時,InnoDB 會根據當前事務的 ReadView 快照信息來判斷能讀取到哪些數據版本。這一過程通過以下幾個步驟實現:

  • 當前查詢事務 ID = Undo Log 裏的事務 ID:如果數據的事務 ID 與當前查詢事務的 ID 匹配,説明該數據是當前事務修改的,當前事務可讀取該數據。
  • Undo Log 事務 ID < 未提交事務的最小事務 ID:如果 Undo Log 中的事務 ID 小於未提交事務的最小事務 ID,説明該數據是在當前查詢事務開始之前就已經提交的,因此該數據可被讀取。
  • Undo Log 事務 ID > 未開始事務的最大事務 ID:如果 Undo Log 中的事務 ID 大於未開始事務的最大事務 ID,説明該數據是在查詢事務開始之後的併發事務中進行修改的,當前事務不能讀取此數據。此時,需要根據 Undo Log 的指針查找下一條數據。
  • Undo Log 事務 ID 在未提交事務的最小事務 ID 和最大事務 ID 之間:如果 Undo Log 中的事務 ID 位於未提交事務的最小和最大事務 ID 之間,説明該數據是在併發的未提交事務中修改的,當前查詢事務不能讀取此數據。此時,查詢會再次進行上述判斷,直到找到符合可讀條件的數據。

4. 讀已提交隔離級別的處理:

  • 讀已提交 隔離級別下,每次查詢的時候都會創建 ReadView 快照,根據這個快照去 Undo Log 裏邊找到數據,查找到符合條件的最新版本數據。
  • 在執行查詢時,如果數據修改是未提交事務所做的,查詢將跳過該數據,直到找到符合條件的數據。

5. 可重複讀隔離級別的處理:

  • 可重複讀 隔離級別下,創建 ReadView 快照只會在第一次讀取時進行,後續的查詢會使用相同的 ReadView 快照。因為可重複讀第一次讀的數據和之後讀的數據一致,所以只需在第一次讀的時候創建快照。
  • 由於同一個快照被多次複用,事務中的讀取操作可以獲得一致的數據版本,避免了“不可重複讀”的問題。

6. 隱藏列的作用:

  • DB_TRX_ID:每一行數據中都會有一個 DB_TRX_ID 列,它記錄了最後修改該行數據的事務 ID。當查詢需要檢查某行數據時,InnoDB 會根據 DB_TRX_ID 來判斷該行數據是否是當前事務能夠讀取的。如果該行的事務 ID 比當前查詢事務的事務 ID 早(即該數據在查詢開始時已提交),則該數據對查詢事務可見。
  • DB_ROLL_PTR:該列指向了該行數據歷史版本的 Undo Log 指針。如果查詢的數據版本不可見,InnoDB 會根據 DB_ROLL_PTR 查找該數據的歷史版本,繼續查找直到找到一個符合條件的可見數據版本。

7. 總結:

  • MVCC通過 隱藏列ReadView 快照Undo Log 來實現數據的併發控制,保證高併發環境下的數據一致性和事務隔離性。
  • 讀已提交和可重複讀的隔離級別分別通過每次查詢創建 ReadView 快照(讀已提交)或僅在首次讀取時創建快照(可重複讀)來控制數據的可見性。
  • 通過比較 Undo Log 中的事務 ID 與當前 ReadView 快照中的信息,InnoDB 判斷一個數據版本是否可見,從而保證數據的隔離性。
user avatar u_17513518 頭像 daimajiangxin 頭像 junxiudedoujiang 頭像 enaium 頭像 icollection 頭像 iicode 頭像
點贊 6 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.