1、概念 mvcc作用在於解決併發條件下,讀寫衝突的問題。一般用於RC和RR隔離級別,解決臟讀和不可重覆讀的問題。 (1)當前讀 讀取的是記錄的最新版本,讀取時還要保證其他事務不能修改當前記錄,會對讀取的記錄進行加鎖。對於我們日常的操作,如:select ... lock in share mo ...
1、概念
mvcc作用在於解決併發條件下,讀寫衝突的問題。一般用於RC和RR隔離級別,解決臟讀和不可重覆讀的問題。
(1)當前讀
讀取的是記錄的最新版本,讀取時還要保證其他事務不能修改當前記錄,會對讀取的記錄進行加鎖。對於我們日常的操作,如:select ... lock in share mode(共用鎖),select ... for update、update、insert、delete(排他鎖)都是一種當前讀。
(2)快照讀
簡單的select 就是快照讀,讀取的是記錄的可見版本, 有可能是歷史數據,不加鎖,不阻塞
-
Read Committed:每次select,都會生成一個快照讀
-
Repeatable Read:開啟事務後第一個select語句才是快照讀的地方。
-
Serializable:快照讀會退化為當前讀。
2、MVCC的條件
要實現MVCC,需要3個條件:3個隱藏欄位,undo log以及readview。
(1)隱藏欄位
表結構中除了行數據以外,還有3個隱藏欄位:
-
DB_TRX_ID:最新修改的事務ID,記錄插入和修改最後一次的事務ID
-
DB_ROLL_PTR :回滾指針,指向上一個版本記錄
-
DB_ROW_ID:隱藏主鍵,如果表結構沒有指定主鍵,將會生成該隱藏欄位。
(2)undo log
回滾日誌,在insert update delete語句執行時保存回滾的日誌。
當insert的時候,產生的undo log日誌只在回滾時需要,在事務提交後,可被立即刪除。
而update、delete的時候,產生的undo log日誌不僅在回滾時需要,在快照讀時也需要,不會立即 被刪除。
不同事務對同一條記錄進行修改後,會生成一條版本連,下圖為undo log中記錄的版本鏈。
(3)readview
ReadView(讀視圖)是 快照讀 SQL執行時MVCC提取數據的依據。
readView包含四個核心欄位:
-
m_ids:當前活躍的事務ID集合
-
min_trx_id:最小活躍事務ID
-
max_trx_id:預分配事務ID,當前最大事務ID+1(因為事務ID是自增的)
-
creator_trx_id:ReadView創建者的事務ID
在readview中就規定了版本鏈數據的訪問規則:
-
trx_id == creator_trx_id:可以訪問該版本 成立,說明數據是當前這個事 務更改的。
-
trx_id < min_trx_id :可以訪問該版本 成立,說明數據已經提交了。
-
trx_id > max_trx_id:不可以訪問該版本 成立,說明該事務是在 ReadView生成後才開啟。
-
min_trx_id <= trx_id <= max_trx_id:如果trx_id不在m_ids中, 是可以訪問該版本的 成立,說明數據已經提交。
不同的隔離級別,生成readview的時機不一樣:
READ COMMITTED :在事務中每一次執行快照讀時生成ReadView。
REPEATABLE READ:在事務第一次執行快照讀的時候生成ReadView。
3、原理分析
(1)RC隔離分析
RC隔離級別是解決臟讀。在事務提交之後才能讀到修改後的記錄。這個是怎麼做到呢,以下圖為例子,事務5在每次快照讀的時候都會生成一個readview。
根據undo log版本鏈記錄和readview的匹配規則,我們來分析以下,事務5第一個查詢,獲取的結果是哪一個呢?
按照上圖中DB_TRX_ID為4,和事務5的第一次查詢的readview進行對比,發現1,2,3,4都不匹配。
然後匹配下一條,DB_TRX_ID為3,和事務5的第一次查詢的readview進行對比,發現1,2,3,4都不匹配。
然後匹配下一條,DB_TRX_ID為2,和事務5的第一次查詢的readview進行對比,發現第二個是匹配的。那就說明此快照讀,返回的是此版本鏈的數據。
事務5第二個查詢,獲取的結果是哪一個呢?
按照上圖中DB_TRX_ID為4,和事務5的第二次查詢的readview進行對比,發現1,2,3,4都不匹配。
然後匹配下一條,DB_TRX_ID為3,和事務5的第二次查詢的readview進行對比,發現第二個是匹配的。那就說明此快照讀,返回的是此版本鏈的數據。
(1)RR隔離分析
RR隔離級別下,僅在事務中第一次執行快照讀時生成ReadView,後續復用該ReadView。 而RR 是可 重覆讀,在一個事務中,執行兩次相同的select語句,查詢到的結果是一樣的。以下圖為例子,事務5在第一次快照讀的時候會生成一個readview,後面就會服用此readview。上述已經分析過每次查詢的記錄在undo log中DB_TRX_ID為2的版本鏈是匹配的。
總結:
MVCC使用隱藏欄位、undo log,readview實現的,沒修改一次都會在undo log中生成一個版本記錄,對於同一條記錄會生成一個版本鏈,每條記錄中包含隱藏欄位。而readview則是在每次快照讀的時候生成,通過版本鏈中的trx_id欄位,對比readview中的記錄,通過readview的規則,判斷哪條版本記錄是匹配的,從而得到最終結果。所以MVCC+鎖實現了事務的隔離性。