Multi-Version Concurrency Control 多版本並發控制,MVCC 是一種並發控制的方法,一般在資料庫管理系統中,實現對資料庫的並發訪問;在程式語言中實現事務記憶體。
基本介紹
- 中文名:MVCC
- 增加:並發性
- 被稱為:多版本並發控制
- 避免:使用鎖
- 保存:某個時間點上的數據快照
產品簡介,說明,比鎖定的優勢,GBase8的特性,
產品簡介
大多數的MySQL事務型存儲引擎,如InnoDB,Falcon以及PBXT都在使用一種簡單的行鎖機制。事實上,他們都和另外一種用來增加並發性的被稱為“多版本並發控制(MVCC)”的機制來一起使用。MVCC不只使用在MySQL中,Oracle、PostgreSQL,以及其他一些資料庫系統也同樣使用它。
你可將MVCC看成行級別鎖的一種妥協,它在許多情況下避免了使用鎖,同時可以提供更小的開銷。根據實現的不同,它可以允許非阻塞式讀,在寫操作進行時只鎖定必要的記錄。
MVCC會保存某個時間點上的數據快照。這意味著事務可以看到一個一致的數據視圖,不管他們需要跑多久。這同時也意味著不同的事務在同一個時間點看到的同一個表的數據可能是不同的。如果你從來沒有過這種體驗的話,可能理解起來比較抽象,但是隨著慢慢地熟悉這種理解將會很容易。
InnoDB:通過為每一行記錄添加兩個額外的隱藏的值來實現MVCC,這兩個值一個記錄這行數據何時被創建,另外一個記錄這行數據何時過期(或者被刪除)。但是InnoDB並不存儲這些事件發生時的實際時間,相反它只存儲這些事件發生時的系統版本號。這是一個隨著事務的創建而不斷增長的數字。每個事務在事務開始時會記錄它自己的系統版本號。每個查詢必須去檢查每行數據的版本號與事務的版本號是否相同。讓我們來看看當隔離級別是REPEATABLE READ時這種策略是如何套用到特定的操作的:
SELECT InnoDB必須每行數據來保證它符合兩個條件:
1、InnoDB必須找到一個行的版本,它至少要和事務的版本一樣老(也即它的版本號不大於事務的版本號)。這保證了不管是事務開始之前,或者事務創建時,或者修改了這行數據的時候,這行數據是存在的。
2、這行數據的刪除版本必須是未定義的或者比事務版本要大。這可以保證在事務開始之前這行數據沒有被刪除。這裡的不是真正的刪除數據,而是標誌出來的刪除。真正意義的刪除是在commit的時候。
符合這兩個條件的行可能會被當作查詢結果而返回。
INSERT:InnoDB為這個新行記錄當前的系統版本號。
DELETE:InnoDB將當前的系統版本號設定為這一行的刪除ID。
UPDATE:InnoDB會寫一個這行數據的新拷貝,這個拷貝的版本為當前的系統版本號。它同時也會將這個版本號寫到舊行的刪除版本里。
這種額外的記錄所帶來的結果就是對於大多數查詢來說根本就不需要獲得一個鎖。他們只是簡單地以最快的速度來讀取數據,確保只選擇符合條件的行。這個方案的缺點在於存儲引擎必須為每一行存儲更多的數據,做更多的檢查工作,處理更多的善後操作。
MVCC只工作在REPEATABLE READ和READ COMMITED隔離級別下。READ UNCOMMITED不是MVCC兼容的,因為查詢不能找到適合他們事務版本的行版本;它們每次都只能讀到最新的版本。SERIABLABLE也不與MVCC兼容,因為讀操作會鎖定他們返回的每一行數據。
說明
通過使用MVCC(Multi-Version Concurrency Control)算法自動提供並發控制。MVCC維持一個數據的多個版本使讀寫操作沒有衝突。也就是說數據元素X上的每一個寫操作產生X的一個新版本,GBase 8m為X的每一個讀操作選擇一個版本。由於消除了資料庫中數據元素讀和寫操作的衝突,GBase 8m得到最佳化,具有更好的性能。特別是對於資料庫讀和寫兩種方法,他們不用等待其他同時進行的相同數據寫和讀的完成。在並發事務中,資料庫寫只等待正在對同一行數據進行更新的寫,這是現有的行級鎖的弱點。同時MVCC回收不需要的和長時間不用的記憶體,防止記憶體空間的浪費。MVCC最佳化了資料庫並發系統,使系統在有大量並發用戶時得到最高的性能,並且可以不用關閉伺服器就直接進行熱備份。
比鎖定的優勢
使用MVCC多版本並發控制比鎖定模型的主要優點是在MVCC里, 對檢索(讀)數據的鎖要求與寫數據的鎖要求不衝突, 所以讀不會阻塞寫,而寫也從不阻塞讀。
在資料庫里也有表和行級別的鎖定機制, 用於給那些無法輕鬆接受 MVCC 行為的套用。 不過,恰當地使用 MVCC 總會提供比鎖更好地性能。
GBase8的特性
在 GBase 中的查詢功能通過 MVCC 提供的一致性非鎖讀(在下文我們簡稱為一致性讀),就是提供通過資料庫在一個時間點上的快照來實現信息的查詢。查詢只是對那些在這個時間點之前提交的事務所做的變更,而並不關注在時間點之後的變更或未提交的事務。當然,若是該事務自身進行的變更,對於查詢是可見的。
GBase 的默認級別是 READ COMMITTED ,在該隔離級別下事務中的查詢語句,使用當前時間戳進行一致性讀,每次查詢的時間戳是不相同的。
但對 REPEATABLE READ 隔離級別,在同一個事務中的所有一致性讀,使用的時間戳均是第一個查詢的時間戳,這樣讀取的也就是由該事務第一次讀建立起來的數據快照。用戶只有通過提交當前事務,並發出一個新的查詢才會得到新的數據快照。
一致性讀是 GBase 在 READ COMMITTED 和 REPEATABLE READ 隔離級別下,處理 SELECT 語句中使用的默認模式。一致性讀在它讀的數據上不設定任何鎖,因此在一致性讀某個表的同時,其它用戶均可以修改這個表。
注意在 DROP TABLE 和 ALTER TABLE 運作時,一致性讀無效 。一致性讀在 DROP TABLE 上無效是因為 GBase 不能使用已經 drop 的表,該表已經刪除。一致性讀在 ALTER TABLE 上無效是因為 GBase 會在事務內,重新創建一個新表並從舊錶向新表插入記錄。這樣當用戶再次執行一致性讀時,在新表中將看不到任何行,因為在新表中的數據都在第一次一致性讀的快照之外。