MySQL 中實現可重復讀(RR)的原理--MVCC


MVCC,多版本並發控制(Multi-Version Conncurrency Control)是mysql中基於樂觀鎖原理實現的隔離級別的方式。用於實現讀已提交和可重復讀取隔離級別。
對於MVCC,是通過在每行記錄后面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的創建時間(事務ID),一個保存行的刪除時間(回滾指針),當然存儲的並不是實際的時間值,而是系統版本號(system version number).每開始一個新的事務,系統版本號都會自動遞增,事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。

MVCC的核心就是 Undo log+ Read-view,“MV”就是通過 Undo log來保存數據的歷史版本,實現多版本的管理,“CC”是通過 Read-view來實現管理,通過 Read-view原則來決定數據是否顯示。同時針對不同的隔離級別, Read view的生成策略不同,也就實現了不同的隔離級別。

簡單說一句話就是:undo log + 版本鏈 + 比較規則

舉例:
如下圖,事務 T-100 和 T-120 對表中 id = 1 的數據行做 update 操作,事務 T-130 進行 select 操作。

從圖中可以看出,即使 T-100 已經提交修改,三次 select 語句的結果都是“lisi”。
整個過程的流程如下圖:

下面詳細講講流程:

當一個事務第一次執行查詢sql時,會生成一致性視圖 read-view(快照),它由執行查詢時所有未提交事務 id 數組(數組中最小的 id 為 min_id)和已創建的最大事務 id(max_id)組成,查詢時從 undo log 中最新的一條記錄開始跟 read-view 做對比,如果不符合比較規則,就根據回滾指針回滾到上一條記錄繼續比較,直到得到符合比較條件的查詢結果。對於上面的例子,事務T-130 在第一次執行select 語句時,生成了 read-view 快照,此時未提交的事務id是100,已提交的事務id是120,所以 read-view :[100],120

undo log 中記錄和 read-view 的比對規則:

  1. 如果當前記錄的事務id落在綠色部分(trx_id < min_id),表示這個版本是已提交的事務生成的,可讀。
  2. 如果當前記錄的事務id落在紅色部分(trx_id > max_id),表示這個版本是由將來啟動的事務生成的,不可讀。
  3. 如果當前記錄的事務id落在黃色部分(min_id <= trx_id <= max_id),則分為兩種情況:
    • 若當前記錄的事務id在未提交事務的數組中,則此條記錄不可讀;
    • 若當前記錄的事務id不在未提交事務的數組中,則此條記錄可讀。

擴展
1)對於刪除的情況
可以認為是update 的特殊情況,會將版本鏈上最新的數據復制一份,然后將 trx_id 修改成刪除操作的 trx_id ,同時在該條記錄的頭信息(record header)里的(deleted_flag)標記位上寫位 true,來表示當前記錄已經被刪除,在查詢時按照上面的規則查到對應的記錄,如果deleted_flag 標記為是true,則說明該條記錄已被刪除,不返回數據。

2)隔離級別 Read Committed 和 Read Repeatable
RC 和 RR 隔離級別都是由 MVCC 實現,區別在於:
RC 隔離級別時,read-view 是每次執行 select 語句時都生成一個;
RR 隔離級別時,read-view 是在第一次執行 select 語句時生成一個,同一事務中后面的所有 select 語句都復用這個 read-view 。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM