輕鬆理解MYSQL MVCC 實現機制

什麼是MVCC?它能解決什麼問題?

MVCC是一種多版本併發控制機制。大多數的MySql事務型存儲引擎,如InnoDB、Falcon等都不只是簡單地使用行鎖機制,它們都和MVCC-多版本併發控制機制一起使用。並且大家都知道可以通過鎖來控制併發操作,但是對於系統來說開銷較大,而MVCC在大部分情況下可以代替行級鎖,使用MVCC可以有效降低系統開銷。並且MVCC可以解決可重複讀級別下的幻讀問題。

InnoDB中MVCC的具體實現分析

下面通過InnoDB來簡單分析MVCC是如何進行併發控制的:

InnoDB的MVCC是通過在每行記錄後面保存兩個隱藏的列來實現的,這兩個列,分別保存了這個行的創建時間和這個行的刪除時間。這個時間並不是實際的時間值,而是系統的版本號(可以理解為事務的ID),每開始一個新的事務,系統版本號就自增,事務開始時刻的系統版本號會作為事務的ID。下面的例子是在Repeatable read隔離級別下,MVCC的具體實現過程。

創建一張test表,主鍵id自增,另有一個屬性字段name:


輕鬆理解MYSQL MVCC 實現機制

插入數據,InnoDB為新插入的每一行保存當前系統版本號作為版本號,

第一個事務,ID為1

//開啟事務

<code>start transaction;/<code>
<code>insert into test values(NULL,'zhangsan');/<code>
<code>insert into test values(NULL,'lisi');/<code>
<code>insert into test values(NULL,'wangwu');/<code>
<code>commit;/<code>

對應的數據如下表所示(我沒有使用Mysql中查出來的表,因為後面兩列是看不到的):


輕鬆理解MYSQL MVCC 實現機制

SELECT

InnoDB會根據以下兩個條件檢查每行記錄,只有同時滿足這兩個條件的記錄,才能返回作為查詢結果:

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

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

DELETE

InnoDB會為刪除的每一行保存當前系統版本號(事務的ID)作為刪除標識。

從下面的例子來分析

第二個事務,ID為2:

<code>start transaction;/<code>
<code>select * from test;   //(1)/<code>
<code>select * from test;   //(2)/<code>
<code>commit;/<code>

假設1

假設在執行這個事務ID為2的過程中,剛執行到(1),這時,有另一個事務ID為3往這個表裡插入了一條數據;

第三個事務,ID為3:

<code>start transaction;/<code>
<code>insert into test values(NULL,'zhaoliu');/<code>
<code>commit;/<code>

這時表中數據如下:


輕鬆理解MYSQL MVCC 實現機制

然後執行事務2中的(2),即select * from test;由於id=4的數據的創建時間(事務ID為3),執行當前事務的ID為2,而InnoDB只會查找事務ID小於或等於當前事務ID的數據行,所以id=4的數據行並不會在執行事務2的(2)中被檢索出來,在事務2的(2)中檢索出來的數據行只會如下表所示:


輕鬆理解MYSQL MVCC 實現機制

假設2

假設在執行事務ID為2的過程中,剛執行到(1),假設執行完事務3以後,接著又執行了事務4。

第四個事務,ID為4:

<code>start transaction;/<code>
<code>delete from test where id=1;/<code>
<code>commit;/<code>

此時test表中數據如下:


輕鬆理解MYSQL MVCC 實現機制

接著執行事務ID為2的事務(2),根據SELECT檢索條件可以知道,它會檢索創建時間(創建事務ID)小於或等於當前事務ID的數據行和刪除時間(刪除事務ID)大於當前事務的行,而id=4的行上面已經說過了,而id=1的行由於刪除時間(刪除事務ID)大於當前事務的ID,所以事務2的(2)select * from test也會把id=1的數據檢索出來。所以事務2中的兩條select語句檢索出來的數據如下所示:


輕鬆理解MYSQL MVCC 實現機制

UPDATE

InnoDB執行UPDATE,實際上是新插入了一行記錄,並保存其創建時間為當前事務的ID,同時保存當前事務的ID到要UPDATE的行的刪除時間。

假設3:

假設在執行完事務2的(1)後,其他用戶又執行了事務3和事務4,這時,又有一個用戶對這張表執行了UPDATE操作:

第五個事務,ID為5:

<code>start transaction;/<code>
<code>update test set name='lisi' where id=2;/<code>
<code>commit;/<code>

根據UPDATE的更新原則:會生成新的一行,並在原來要修改的列的刪除時間列上添加本事務ID,如下表所示:


輕鬆理解MYSQL MVCC 實現機制

得到的結果還是和事務2中(1)檢索出的結果相同。

示例參考:https://blog.csdn.net/whoamiyang/article/details/51901888#commentBox


分享到:


相關文章: