Multi-Version Concurrency Control 多版本並發控制
大多數的MySQL事務型存儲引擎,如InnoDB,Falcon以及PBXT都不使用一種簡單的行鎖機制。
事實上,他們都和和另外一種用來增加並發性的被稱為“多版本並發控制(MVCC)”的機制來一直使用。
MVCC不只使用在MySQL 中,Oracle,PostgreSQL以及其他一些數據為系統也同樣使用它。
你可將將MVCC看成行級別鎖的一種妥協,它在許多情況下避免了使用鎖,同時可以提供更小的開銷。
根據實現的不同,它可以允許非阻塞式讀,在寫操作進行時只鎖定必要的記錄。
MVCC會保存某個時間點上的數據快照。
這意味阒事務可以看到一個一致的數據視圖,不管他們需要跑多久。
這同時也意味著不同的事務在同一個時間點看到的同一個表的數據可能是不同的。
如果你從來沒有過種體驗的話,可能理解起來比較抽象,但是隨著慢慢地熟悉這種理解將會很容易。
各個存儲引擎對於MVCC的實現各不相同。
這些不同中的一些包括樂觀和悲觀並發控制。
我們將通過一個簡化的InnoDB版本的行為來展示MVCC工作的一個側面。
InnoDB:通過為每一行記錄添加兩個額外的隱藏的值來實現MVCC,這兩個值一個記錄這行數據何時被創建,另外一個記錄這行數據何時過期(或者被刪除)。但是InnoDB並不存儲這些事件發生時的實際時間,相反它只存儲這些事件發生時的系統版本號。這是一個隨著事務的創建而不斷增長的數字。每個事務在事務開始時會記錄它自己的系統版本號。每個查詢必須去檢查每行數據的版本號與事務的版本號是否相同。讓我們來看看當隔離級別是REPEATABLE READ時這種策略是如何應用到特定的操作的: SELECT InnoDB必須每行數據來保證它符合兩個條件:
1、InnoDB必須找到一個行的版本,它至少要和事務的版本一樣老(也即它的版本號不大於事務的版本號)。這保證了不管是事務開始之前,或者事務創建時,或者修改了這行數據的時候,這行數據是存在的。
2、這行數據的刪除版本必須是未定義的或者比事務版本要大。這可以保證在事務開始之前這行數據沒有被刪除。
符合這兩個條件的行可能會被當作查詢結果而返回。
INSERT:InnoDB為這個新行記錄當前的系統版本號。
DELETE:InnoDB將當前的系統版本號設置為這一行的刪除ID。
UPDATE:InnoDB會寫一個這行數據的新拷貝,這個拷貝的版本為當前的系統版本號。
它同時也會將這個版本號寫到舊行的刪除版本裡。
這種額外的記錄所帶來的結果就是對於大多數查詢來說根本就不需要獲得一個鎖。
他們只是簡單地以最快的速度來讀取數據,確保只選擇符合條件的行。
這個方案的缺點在於存儲引擎必須為每一行存儲更多的數據,做更多的檢查工作,處理更多的善後操作。
MVCC只工作在REPEATABLE READ和READ COMMITED隔離級別下。
READ UNCOMMITED不是MVCC兼容的,因為查詢不能找到適合他們事務版本的行版本;
它們每次都只能讀到最新的版本。
SERIABLABLE也不與 MVCC兼容,因為讀操作會鎖定他們返回的每一行數據[1]。