MVCC,多版本并發控制
-
定義:維護一個數據的多個版本,使讀寫操作沒有沖突,依賴于:隱藏字段,undo log日志,readView
-
MVCC會為每條版本記錄保存三個隱藏字段
- DB_TRX_ID: 記錄最近插入或修改該記錄的事務ID
- DB_ROLL_PTR:回滾指針,指向這條記錄的上個版本,配合undo log
- DB_ROW_ID:隱藏主鍵,如果沒有指定主鍵,將會生成該隱藏主鍵
流程(重點):在修改數據前,innodb引擎會在undo log日志拷貝一份原記錄,并將其DB_ROLL_PTR指向上一個版本,形成版本鏈。然后修改數據值,并把DB_TRX_ID改為當前執行的事務ID。
-
readView
-
定義:確定事務在快照讀時能夠看到數據庫中的哪些數據版本。
-
區分:
當前讀:讀取的是記錄的最新版本,對讀取的記錄加鎖,保證讀取時其他并發事務不能修改當前記錄,解決幻讀
快照讀:select查詢,不加鎖,讀取記錄數據的可見版本(通過事務ID遞增性判斷是否可見)
- Read Commited:每次select都生成一個readView,讀取可見記錄中的最新版本,會造成不可重復讀的問題
- Repetable Read:事務首次 select時生成 readView,后續復用該readView**
-
-
定義:確定事務在快照讀時能夠看到數據庫中的哪些數據版本。
-
區分:
當前讀:讀取的是記錄的最新版本,對讀取的記錄加鎖,保證讀取時其他并發事務不能修改當前記錄,解決幻讀
快照讀:select查詢,不加鎖,讀取記錄數據的可見版本(通過事務ID遞增性判斷是否可見)
- Read Commited:每次select都生成一個readView,讀取可見記錄中的最新版本,會造成不可重復讀的問題
- Repetable Read:事務首次 select時生成 readView,后續復用該readView
-
流程:基于快照讀生成的readview,跟要查詢的行數據的mvcc版本的DB_TRX_ID做比較,基于事務ID的遞增性判斷mvcc版本是否對當前readview可見,如果可見則返回當前mvcc版本的行數據,如果不可見,則通過mvcc的回滾指針回退到上一個版本。
-
判斷MVCC版本是否對當前readView可見:mvcc版本的DB_TRX_ID字段 與 readView的字段比較,滿足以下任意條件:
- DB_TRX_ID < min_trx_id(最小事務ID):該版本的事務比所有活躍事務(正在運行)更早創建且已提交,因此可見
- DB_TRX_ID = creator_trx_id(創建該readview的事務ID):當前事務自己生成的版本(即使未提交),對自己總是可見
- DB_TRX_ID < max_trx_id(預分配事務ID)&& DB_TRX_ID not in m_ids(活躍的事務ID列表中): 該版本的事務不在創建 read view 時的活躍事務列表中,說明已提交