MySQL資料庫的多版本並發控制之什麼是MVCC?InnoDB的MVCC實現

什麼是MVCC

MySQL的默認隔離級別REPEATABLE READ(可重復讀)解決瞭臟讀,不可重復讀問題,但還是無法解決幻讀的問題。所謂幻讀,指的是A事務讀取某個范圍內的記錄時,另外一個B事務又在該范圍內插入瞭新的記錄,A事務再次讀取該范圍的記錄時,會產生幻行。

InnoDB和XtraDB存儲引擎通過多版本並發控制(Multiversion Concurrency Control)MVCC解決瞭幻讀的問題。

不僅是MySQL,包括Oracle,PostgreSQL等資料庫系統也都實現瞭MVCC。

MVCC並沒有正式的規范,也沒有一個統一的實現標準。不同的資料庫實現的機制不盡相同,不同的存儲引擎的MVCC實現也不同,雖然實現機制有所不同,但大都實現瞭非阻塞的讀操作,寫操作也隻是鎖定必要的行。典型的有樂觀並發控制和悲觀並發控制。

下面通過InnoDB存儲引擎來看下MVCC是如何工作的。

InnoDB的MVCC實現

InnoDB的MVCC,是通過在每行記錄後面保存兩個隱藏的列來實現的。這兩個列,一個保存瞭行的創建時間,一個保存行的過期時間。該時間並不是實際的系統時間值,而是系統版本號(system version number)。每開始一個新的事務,系統版本號都會自動遞增,這是MySQL伺服器的機制。

事務開始時刻的系統版本號會作為該事務的版本號,用來和查詢到的每行記錄的版本號進行比較。

InnoDB在默認隔離級別REPEATABLE READ(可重復讀)下,MVCC具體操作如下:

SELECT

a.隻查找創建時間版本早於當前事務版本的數據行,這樣確保查詢出來的行,要麼是在事務開始前已經存在的,要麼是事務這身插入或者修改過的。

b.行的刪除時間版本號要麼未設定,要麼大於當前事務版本號。這樣可以確保事務讀取到的行,在事務開始之前未被刪除。

INSERT

InnoDB為新插入的每一行保存當前系統版本號作為創建版本號。

DELETE

InnoDB為刪除的每一行保存當前系統版本號作為刪除版本號。

UPDATE

InnoDB為更新的每一行保存當前系統版本號到原來的創建版本號,同時保存當前系統版本號到原來的行作為行刪除版本號。

MVCC的優缺點

優點:保存這兩個額外系統版本號,使大多數讀操作都可以不用加鎖。這樣設計使得讀操作簡單,性能更好,並且保證讀到的數據是符合標準的行。

缺點:每行記錄都需要額外的存儲空間,需要做更多的行檢查工作,更多額外的維護工作。

註意點

MySQL的MVCC隻在REPEATABLE READ(可重復讀)和READ COMMITTED(提交讀)這兩個隔離級別下工作。另外兩個隔離級別和MVCC不兼容,READ UNCOMMITTED(未提交讀)總是讀取最新的數據行,SERIALIZABLE(可串行化)則會對所有讀取的行都加鎖。

發佈留言