淺談mysql mvcc


以下為個人理解,如有錯誤,還望指正!!

 

mysql的大多數事務型存儲引擎實現的都不是簡單的行級鎖,基於提升並發性能的考慮,他們一般都同時實現了多版本並發控制,可以認為MVCC是行級鎖的一個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低,雖然實現機制有所不同,但大都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。

MVCC的實現是通過保存數據在某個時間點的快照來實現的,也就是說,不管需要執行多長時間,只要事務開始時間相同,每個事務看到的數據都是一致的,事務開始的時間不同時,每個事務對同一張表,同一時刻看到的數據可能是不一樣的(因為不同的時間點可能數據就已經產生了不同的快照版本,而每個事務在默認的RR隔離級別下只能看到事務開始時的數據快照)。說道不同的存儲引擎的MVCC實現是不同的,典型的有樂觀並發控制和悲觀並發控制,下面簡單說明MVCC是如何工作的:

innodb的MVCC,是通過在每行記錄后面保存兩個隱藏的列來實現的,這兩個列,一個保存了行的創建時間,一個保存了行的過期時間(或刪除時間),當然,存儲的並不是實際的時間值,而是系統版本號(system version number),每開始一個新的事務,系統版本號都會自動遞增,事務開始時刻的系統版本號作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較,下面看repeatable read隔離級別下,MVCC具體是如何操作的:

select:

innodb會根據以下兩個條件檢查每行的記錄

A:innodb只查找版本早於當前事務版本的數據行(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要么是在事務開始之前已經存在,要么是事務自身插入或修改的數據。

B:行的刪除版本要么未定義,要么大於當前事務版本號,這可以確保事務讀取到的行,在事務開始之前未被刪除(即,這樣做的目的是為了事務不會讀取到被真正刪除的行,刪除版本號小於當前事務版本號的表示操作刪除記錄的事務已經提交--數據已經被刪除,刪除版本號大於當前事務版本號的表示這個事務是在當前事務之后開始的--當前事務開始時這些記錄是還存在的,根據事務的隔離性,一致性要求,之后開始的事務操作的記錄並提交,對當前事務不可見,所以還需要當前事務能夠查詢這些記錄--只能夠查詢,不能夠修改和刪除)。

只有滿足以上兩個條件的才可以返回作為查詢結果。

 

insert:

innodb為新插入的每一行保存當前系統版本號作為行版本號

delete:

innodb為刪除的每一行保存當前系統版本號作為行刪除標識

update:

innodb為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識

 

保存這兩個額外的系統版本號,使大多數讀操作都可以不用加鎖,這樣設計使得讀數據操作很簡單,性能很好,並且也能保證只會讀取到符合標准的行,不足之處是每行記錄都需要額外的存儲空間,需要做更多的行檢查工作,以及一些額外的維護工作。

MVCC只在repeatable-read和read-committed兩個隔離級別下才工作,其他兩個隔離級別都和MVCC不兼容,因為read uncommitted總是讀取最新的數據行,而不是符合當前事務版本的數據行,而serializeble則會對所有讀取的行都加鎖。

另外要注意:MVCC在RR和RC隔離級別下的區別,在RR隔離級別下,一個事務只能讀取到事務開始的那個時刻的數據快照,即,別的事務修改並提交的數據在自身沒有提交之前一般讀取不到(加for update語句的select除外,因為這個語句要對數據加X鎖必須讀取最新的數據快照),在RC隔離級別下,事務總是讀取數據行的最新快照,即會產生不可重復讀的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM