【MySQL學習筆記】MVCC多版本併發控制

MVCC 原理

1. 概念

MVCC 是爲了解決事務併發執行過程中所遇到的問題。

2. 版本鏈

對於使用 InnoDB 存儲索引的表來說,它的聚簇索引記錄中都包含兩個必要的隱藏列,如下

  • trx_id:每次一個事務對某條聚簇索引記錄進行改動時,都會把該事務的事務 id 賦值給 trx_id 隱藏列。
  • roll_pointer:每次一個事務對某條聚簇索引記錄進行改動時,都會把舊的版本寫入 undo 日誌中,然後這個隱藏列就相當於一個指針,指向 insert undo,可以通過它來找到該記錄修改前的信息,即記錄上一個版本。

實際上,insert undo 只在事務回滾時起作用,當事務提交後,該類型的 undo 日誌就沒用了,它佔用的 Undo Log Segment 也會被系統回收,但是雖然真正的 insert undo 日誌佔用的存儲空間被釋放了,但是 roll_pointer 的值並不會被清除。

每次對記錄進行改動,都會記錄一條 undo 日誌,每條 undo 日誌也都有一個 roll_pointer 屬性,可以將這些 undo 日誌都連起來,串成一個鏈表

在這裏插入圖片描述

每次對記錄進行更新,都會產生一條 undo 日誌,並將最新版本的 roll_pointer 指針指向舊版本,這樣就通過 roll_pointer 形成了一條鏈表,我們把這條鏈表稱之爲版本鏈,版本鏈的頭節點就是當前最新的值。另外,每個版本中還包含生成該版本時對應的事務 id。

3. ReadView

對於使用 read uncommited 隔離級別的事務來說,由於可以讀到未提交事務修改過的記錄,所以直接讀取記錄的最新版本就好了;對於使用 serializable 隔離級別的事務來說,InnoDB中規定使用鎖的方式來訪問記錄;對於使用 read commited 和 repeatable read 隔離級別的事務來講,都必須保證讀到了已經提交了的事務修改過的記錄。

爲了判斷版本鏈中哪個版本是當前事務可見的,InnoDB 中提出了一個 ReadView 的概念,其中包含四個重要內容,如下:

  • m_ids:表示在生成 ReadView 時當前系統中活躍的讀寫事務的事務 id 列表。
  • min_trx_id:表示在生成 ReadView 時當前系統中活躍的讀寫事務中最小的事務 id,也就是 m_ids 中的最小值。
  • max_trx_id:表示生成 ReadView 系統中應該分配給下一個事務的 id 值。
  • creator_trx_id:表示生成該 ReadView 的事務的事務 id。

在訪問某條記錄時,判斷記錄版本是否可見的步驟:

  • 如果被訪問版本的 trx_id 屬性值與 ReadView 中的 creator_trx_id 值相同,意味着當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問。
  • 如果被訪問版本的 trx_id 屬性值小於 ReadView 中的 min_trx_id 值,表明生成版本的事務在當前事務生成 ReadView 前已經被提交,所以該版本可以被當前事務訪問。
  • 如果被訪問版本的 trx_id 屬性值在 ReadView 的 min_trx_id 和 max_trx_id 之間,那就需要判斷一下 trx_id 屬性值是不是在 m_ids 列表中,如果在,說明創建 ReadView 時生成該版本的事務還是很活躍的,該版本不可被訪問,如果不在,說明創建 ReadView 時該版本的事務已經被提交,該版本可以被訪問。

在 MySQL 中,READ COMMITTED 和 REPEATABLE READ 隔離級別一個大的區別就是它們生成 ReadView 的時機不同。

READ COMMITTED ---- 每次讀取數據前都生成一個 ReadView

REPEATABLE READ ---- 在第一次讀取數據時生成一個 ReadView

4. MVCC 總結

所謂的 MVCC 指的是在使用 READ COMMITED、REPEATABLE READ 這兩種隔離級別的事務在執行普通的 SELECT 操作時訪問記錄的版本鏈的過程,這樣可以使不同事務的讀-寫、寫-讀操作併發控制,從而提高系統性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章