多版本并發控制
什么是MVCC
MVCC (Multiversion Concurrency Control)多版本并發控制。顧名思義,MVCC是通過數據行的多個版本管理來實現數據庫的并發控制。這項技術使得在InnoDB的事務隔離級別下執行一致性讀操作有了保證。換言之,就是為了查詢一些正在被另一個事務更新的行,并且可以看到它們被更新之前的值,這樣在做查詢的時候就不用等待另一個事務釋放鎖。
快照讀與當前讀
再談隔離級別
MVCC 可以不采用鎖機制,而是通過樂觀鎖的方式來解決不可重復讀和幻讀問題!它可以在大多數情況下替代行級鎖,降低系統的開銷。
隱藏字段、Undo Log 版本鏈
MVCC實現原理之ReadView
MVCC的實現依賴于:隱藏字段、Undo log版本鏈、ReadView
什么是ReadView?
在MVCC機制中,多個事務對同一個行記錄進行更新會產生多個歷史快照,這些歷史快照保存在Undo Log里**。如果一個事務想要查詢這個行記錄,需要讀取哪個版本的行記錄呢?這時就需要用到ReadView了**,它幫助我們解決了行的可見性問題。
ReadView就是事務在使用MVCC機制進行快照讀操作時產生的讀視圖。當事務啟動時,會生成數據庫系統當前的一個快照,InnoDB為每個事務構造了一個數組,用來記錄并維護系統當前活躍事務的ID(“活躍”指的就是,啟動了但還沒提交)
設計思路
ReadView要解決的主要問題就是需要判斷一下版本鏈中的哪個版本是當前事務可見的。
ReadView的規則
有了ReadView,在訪問某條記錄時,只需要按照下面的步驟判斷記錄的某個版本是否可見。
-
如果被訪問版本的trx_id屬性值與ReadView中的creator_trx_id值相同,意味著當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問。
-
如果被訪問版本的trx_id值小于ReadView中的up_limit_id值,表明生成該版本的事務在當前事務生成ReadView前已提交,所以該版本可以被當前事務訪問。
-
如果被訪問版本的trx_id值大于或等于ReadView中low_limit_id值,表明生成該版本的事務在當前事務生成的ReadView后才開啟,所以該版本不可以被當前事務訪問。
-
如果被訪問版本的trx_id值在ReadView的up_limit_id和low_limit_id之間,那就需要判斷一下trx_id屬性值是不是在trx_ids列表中。
如果在,說明創建ReadView時生成該版本的事務還是活躍的,該版本不可以被訪問。
如果不在,說明創建ReadView時生成該版本的事務已經被提交,該版本可以被訪問。
MVCC整體操作流程
事務的隔離級別為讀已提交時,一個事務中的每一次SELECT查詢都會重新獲取一次Read View。
當事務隔離級別為可重復讀時,就避免了不可重復讀。這是因為一個事務只在第一次SELECT的時候會獲取一次Read View,而后面的所有的SELECT都會復用這個Read view。
舉例說明
READ COMMITTED 隔離級別下
之后,把事務id為10的事務提交
這個時候再讀一次:
執行過程分析:
REPEATABLE READ隔離級別下
如何解決幻讀?
總結
B站鏈接