MVCC
事務的隔離級別分為四種,其中Read Committed和Repeatable Read隔離級別,部分實現就是通過MVCC(Multi-Version Concurrency Control,多版本并發控制)
版本鏈
-
版本鏈是通過undo日志實現的,
-
事務每次修改一次記錄,都會生成一條undo日志,將記錄被修改字段之前的值、trx_id、roll_pointer寫到undo日志中,
-
修改記錄的同時將當前事務的id賦值給記錄的trx_id,記錄的roll_pointer指向剛生成的undo日志,這樣子就構成了由roll_pointer字段串起來的鏈表,叫做版本鏈。
-
-
當然插入類型的undo日志沒有roll_pointer,是版本鏈的尾節點,當然它對于MVCC機制也沒有作用。
ReadView
ReadView(一致性視圖)是實現Read Committed和Repeatable Read隔離級別的一個重要結構。上述兩種隔離級別,要求事務不能讀到另一個活躍事務沒有沒有提交的修改的記錄。當檢索到該條記錄,就會通過ReadView中的屬性對比記錄和undo日志上的trx_id進行篩選,不符合條件則按照版本鏈不斷向后遍歷。
-
ReadView中包含以下屬性:
-
m_ids:創建ReadView時,當前系統中活躍的讀寫事務的id列表。
-
min_trx_id:創建ReadView時,當前系統中活躍的讀寫事務的最小id,也就是m_ids的最小值。
-
max_trx_id:創建ReadView時,系統應該分配給下一個事務的id。不是m_ids的最大值。
-
creator_trx_id:創建ReadView的事務的id
-
-
過濾可視記錄
-
針對聚簇索引記錄:訪問記錄的篩選過程,如果符合條件,則會返回結果,否則沿著版本鏈向后遍歷,當前訪問呢記錄的trx_id如果
-
小于min_trx_id,則說明修改該記錄的事務已經提交,符合要求。
-
大于等于max_trx_id,則說明修改該記錄的事務在創建ReadView時還未出生,不符合要求。
-
被包含在m_ids,則說明修改該記錄的事務在創建ReadView時還未提交,不符合要求
-
等于creator_id,則說明這條記錄就是自己改的,符合要求。
-
其他情況都符合要求。
-
-
二級索引記錄:首先會根據記錄所在頁的的Page Header的PAGE_MAX_TRX_ID屬性(表示修改該頁的最大的事務id)進行粗略判斷
-
如果該值小于min_trx_id,則該頁的所有記錄都符合要求,可以被當前事務看見
-
否則就會回表,通過聚簇索引記錄來判斷。
-
-
-
隔離級別運用
-
Read Committed:每次讀取數據前創建一個ReadView,可能會導致,同一個事務讀取同一條記錄兩次,結果都不一樣(期間有事務修改記錄并提交了)
-
Repeatable Read:每個事務第一次讀取記錄前創建一個ReadView,該事務內讀取所有數據都一致。
-
purge階段
-
每個事務生成的undo日志被劃為一組,并且事務提交時,還會生成一個事務no分配給這組undo日志(事務no全局變量,每次分配后自增1)
-
生成ReadView時會獲取當前系統的事務no并且加一存儲起來(這個不算分配)
-
-
如果undo日志組的事務no小于當前系統事務no最小的ReadView的事務no,則說明這組事務永遠不會被訪問到,就可以被回收了,如果這組undo日志中有邏輯刪除記錄的情況,則將這條記錄徹底刪除。