MVCC,多版本並行控制協定,是資料庫中經常使用的的一種並行控制手段,是MySQL中基於樂觀鎖理論實現隔離級別的方式,用於實現讀已提交和可重複讀取隔離級別的實現
MVCC最大的好處是:讀不加鎖,讀寫不衝突。在讀多寫少的OLTP應用中,讀寫不衝突是非常重要的,極大的提高了系統的並行性
Mysql在可重複讀隔離級別下如何保證事務較高的隔離性,同樣的sql查詢語句在一個事務裡多次執行查詢結果相同,就算其它事務對資料有修改也不會影響當前事務sql語句的查詢結果。
這個隔離性就是靠MVCC(Multi-Version Concurrency Control)機制來保證的,對一行資料的讀和寫兩個操作預設是不會通過加鎖互斥來保證隔離性,避免了頻繁加鎖互斥,而在序列化隔離級別為了保證較高的隔離性是通過將所有操作加鎖互斥來實現的。
Mysql在讀已提交和可重複讀隔離級別下都實現了MVCC機制。
MVCC就一句話總結:同一份資料臨時儲存多個版本的一種方式,進而實現並行
快照讀和當前讀
在MVCC並行控制中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read),快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖,當前讀,讀取的是記錄的最新版本,並且當前讀返回的記錄,都會加上鎖,保證其他事務不會再並行修改這條記錄
快照讀: 簡單的select操作,屬於快照讀,不加鎖
當前讀: 特殊的讀操作,插入/更新/刪除操作,屬於當前讀,需要加鎖
select * from table where ? lock in share mode;
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;
所有以上的語句,都屬於當前讀,讀取記錄的最新版本,並且讀取之後,還需要保證其他並行事務不能修改當前記錄,對讀取記錄加鎖
其中,除了第一條語句,對讀取記錄加S鎖 (共用鎖)外,其他的操作,都加的是X鎖 (排它鎖)
InnoDB的MVCC,是通過在每行記錄後面儲存兩個隱藏的列來實現的,這兩個列,分別儲存了這個行的建立時間,一個儲存的是行的刪除時間
一個行記錄資料有多個版本對快照資料,這些快照資料在undo log中
這裡儲存的並不是實際的時間值,而是系統版本號(可以理解為事務的ID),每開始一個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的ID
INSERT
InnoDB為新插入的每一行儲存當前系統版本號作為版本號
SELECT
InnoDB會根據以下兩個條件檢查每行記錄:
a.InnoDB只會查詢建立的版本號早於當前事務版本的資料行
(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要麼是在事務開始前已經存在的,要麼是事務自身插入或者修改過的
b.行的刪除版本要麼未定義,要麼大於當前事務版本號
這可以確保事務讀取到的行,在事務開始之前未被刪除
只有a,b同時滿足的記錄,才能返回作為查詢結果
DELETE
InnoDB會為刪除的每一行儲存當前系統的版本號(事務的ID)作為刪除標識
UPDATE
InnoDB執行UPDATE,實際上是新插入了一行記錄,並儲存其建立時間為當前事務的ID,同時儲存當前事務ID到要UPDATE的行的刪除時間