可重複讀實現原理MVCC

準備

測試環境:Mysql 5.7.20-log

數據庫默認隔離級別:RR(Repeatable Read,可重複讀),MVCC主要適用於Mysql的RC,RR隔離級別

創建一張存儲引擎爲testmvcc的表,sql爲:

  1. CREATE TABLE testmvcc (
  2. id int(11) DEFAULT NULL,
  3. name varchar(11) DEFAULT NULL
  4. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

什麼是MVCC?

英文全稱爲Multi-Version Concurrency Control,翻譯爲中文即 多版本併發控制。在小編看來,他無非就是樂觀鎖的一種實現方式。在Java編程中,如果把樂觀鎖看成一個接口,MVCC便是這個接口的一個實現類而已。

Mysql中MVCC的使用及原理詳解

 

特點

1.MVCC其實廣泛應用於數據庫技術,像Oracle,PostgreSQL等也引入了該技術,即適用範圍廣

2.MVCC並沒有簡單的使用數據庫的行鎖,而是使用了行級鎖,row_level_lock,而非InnoDB中的innodb_row_lock.

基本原理

MVCC的實現,通過保存數據在某個時間點的快照來實現的。這意味着一個事務無論運行多長時間,在同一個事務裏能夠看到數據一致的視圖。根據事務開始的時間不同,同時也意味着在同一個時刻不同事務看到的相同表裏的數據可能是不同的。

基本特徵

  • 每行數據都存在一個版本,每次數據更新時都更新該版本。
  • 修改時Copy出當前版本隨意修改,各個事務之間無干擾。
  • 保存時比較版本號,如果成功(commit),則覆蓋原記錄;失敗則放棄copy(rollback)

InnoDB存儲引擎MVCC的實現策略

在每一行數據中額外保存兩個隱藏的列:當前行創建時的版本號和刪除時的版本號(可能爲空,其實還有一列稱爲回滾指針,用於事務回滾,不在本文範疇)。這裏的版本號並不是實際的時間值,而是系統版本號。每開始新的事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會作爲事務的版本號,用來和查詢每行記錄的版本號進行比較。

每個事務又有自己的版本號,這樣事務內執行CRUD操作時,就通過版本號的比較來達到數據版本控制的目的。

MVCC下InnoDB的增刪查改是怎麼work的

1.插入數據(insert):記錄的版本號即當前事務的版本號

執行一條數據語句:insert into testmvcc values(1,"test");

假設事務id爲1,那麼插入後的數據行如下:

Mysql中MVCC的使用及原理詳解

 

2、在更新操作的時候,採用的是先標記舊的那行記錄爲已刪除,並且刪除版本號是事務版本號,然後插入一行新的記錄的方式。

比如,針對上面那行記錄,事務Id爲2 要把name字段更新

update table set name= 'new_value' where id=1;

Mysql中MVCC的使用及原理詳解

 

3、刪除操作的時候,就把事務版本號作爲刪除版本號。比如

delete from table where id=1;

Mysql中MVCC的使用及原理詳解

 

4、查詢操作:

從上面的描述可以看到,在查詢時要符合以下兩個條件的記錄才能被事務查詢出來:

1) 刪除版本號未指定或者大於當前事務版本號,即查詢事務開啓後確保讀取的行未被刪除。(即上述事務id爲2的事務查詢時,依然能讀取到事務id爲3所刪除的數據行)

2) 創建版本號 小於或者等於 當前事務版本號 ,就是說記錄創建是在當前事務中(等於的情況)或者在當前事務啓動之前的其他事物進行的insert。

(即事務id爲2的事務只能讀取到create version<=2的已提交的事務的數據集)

補充:

1.MVCC手段只適用於Msyql隔離級別中的讀已提交(Read committed)和可重複讀(Repeatable Read).

2.Read uncimmitted由於存在髒讀,即能讀到未提交事務的數據行,所以不適用MVCC.

原因是MVCC的創建版本和刪除版本只要在事務提交後纔會產生。

3.串行化由於是會對所涉及到的表加鎖,並非行鎖,自然也就不存在行的版本控制問題。

4.通過以上總結,可知,MVCC主要作用於事務性的,有行鎖控制的數據庫模型。

關於Mysql中MVCC的總結

客觀上,我們認爲他就是樂觀鎖的一整實現方式,就是每行都有版本號,保存時根據版本號決定是否成功。

但由於Mysql的寫操作會加排他鎖(前文有講),如果鎖定了還算不算是MVCC?

瞭解樂觀鎖的小夥伴們,都知道其主要依靠版本控制,即消除鎖定,二者相互矛盾,so從某種意義上來說,Mysql的MVCC並非真正的MVCC,他只是借用MVCC的名號實現了讀的非阻塞而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章