MYSQL 初窺MVCC實現

一,何為MVCC

1,什麼是MVCC

MVCC是一種通過多版本併發控制機制來提高併發的技術

2,MVCC解決的問題

MySQL的大多數事務型存儲引擎實現的都不是簡單的行級鎖。

基於提升併發性能的考慮,它們一般都同時實現了多版本併發控制(MVCC)。

不僅僅是MySQL,包括Oracle,PostgreSQL等其他數據庫系統也都實現了MVCC,但是各自的實現機制並不相同,因為MVCC並沒有一個統一的標準。

MVCC在很多情況下避免了加鎖操作,因此開銷更低。大多數的MVCC都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。

3,MVCC如何實現

MVCC是通過保存數據在某個時間點的快照來實現的。也就是說,不管需要執行多長時間,每個事務看到的數據是一致的。

根據事務開始的時間不同,每個事物對同一張表,同一時刻看到的數據可能是不一樣的。

不同存儲引擎的MVCC實現是不同的,典型的有樂觀(optimistic)併發控制和悲觀(pessimistic)併發控制。

MVCC只在REPEATABLE READ和READ COMMITTED兩個隔離級別下工作。其他兩個隔離級別都和MVCC不兼容,因為READ UNCOMMITTED總是讀取最新的數據行,而不是符合當前事務版本的數據行,而SERIALIZABLE會對所有讀取到的行都加鎖

二,MVCC實現原理

目前比較典型實現MVCC的引擎為InnoDB,所以我們用InnoDB的MVCC實現來解釋他如何進行併發控制的

InnoDB的MVCC,是通過在每行記錄後面保存兩個隱藏的列來實現的,

這兩個列,分別保存了這個行的創建時間,一個保存的是行的刪除時間。這裡存儲的並不是實際的時間值,而是系統版本號(可以理解為事務的ID),

每開始一個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的ID.

我們在REPEATABLE READ隔離級別下來觀察MVCC具體是如何進行的.

1,先創建一張表


MYSQL 初窺MVCC實現

2,假設系統的版本號從1開始.

使用INSERT

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

第一個事務ID為1;


MYSQL 初窺MVCC實現

對應在數據中的表如下(後面兩列是隱藏列,我們通過查詢語句並看不到)


MYSQL 初窺MVCC實現

事物1


使用SELECT

InnoDB會根據以下兩個條件檢查每行記錄:

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

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

只有以上同時滿足的記錄,才能返回作為查詢結果.


使用DELETE

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

看下面的具體例子分析:

第二個事務,ID為2;


MYSQL 初窺MVCC實現

事物2

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

第三個事務ID為3;


MYSQL 初窺MVCC實現

事物3

這時表中的數據如下:


MYSQL 初窺MVCC實現

然後接著執行事務2中的(2),由於id=4的數據的創建時間(事務ID為3)。

執行當前事務的ID為2,而InnoDB只會查找事務ID小於等於當前事務ID的數據行,

所以id=4的數據行並不會在執行事務2中的(2)被檢索出來,

在事務2中的兩條select 語句檢索出來的數據都只會下表:

MYSQL 初窺MVCC實現

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

第四個事務:


MYSQL 初窺MVCC實現

事物4

此時數據庫中的表如下:

MYSQL 初窺MVCC實現

接著執行事務ID為2的事務(2)

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

MYSQL 初窺MVCC實現

使用UPDATE

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

同時保存當前事務ID到要UPDATE的行的刪除時間.

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

第5個事務:

MYSQL 初窺MVCC實現

事物5

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

MYSQL 初窺MVCC實現

繼續執行事務2的(2),根據select 語句的檢索條件,得到下表:

MYSQL 初窺MVCC實現

還是和事務2中(1)select 得到相同的結果.


MYSQL 初窺MVCC實現


分享到:


相關文章: