【MySQL】究竟什么是MVCC呢?


一、MVCC是什么呢?

MVCC其實就是一個多版本並發控制,即多個不同版本的數據實現並發控制的技術,其基本思想是為每次事務生成一個新版本的數據,

在讀數據時選擇不同版本的數據即可以實現對事務結果的完整性讀取。

 

二、MVCC主要有什么作用呢?

提高並發讀寫性能,操作時會生成事務id

1》每條記錄都會保存兩個隱藏列:【trx_id】(事務id)和roll_pointer(回滾指針

2》每次操作都會生成一條undo_log日志,回滾指針指向前一條記錄

查詢的時候會讀取出【read-view】:[未提交的事務id]數組+最大事務id,並根據read-view從undo_log日志中最新的記錄一次往下找,查找規則如下:

①從最新記錄開始查找:

如果當前記錄:事務id < 未提交事務的最小id,則可讀

如果當前記錄:最小id <= 事務id <= 事務的最小id,則判斷事務id是否在未提交事務id的數組中,若在則不可讀(如果只有自己還是可讀)

如果當前記錄:事務id > 事務的最大id,則不可讀

②可重復讀返回的是第一次查詢生成的【read-view】,讀已提交每次都會重新生成一個新的【read-view】

MVCC只能實現讀已提交可重復讀如果是讀未提交,那么每次查詢都能獲取最新的修改值。

  

三、Don‘t BB,看個案例先回顧一下事物的隔離級別:

 

 

 

那么事務A在提交前后,事務B讀取到的x值是什么樣的呢?答案是:事務B在不同隔離級別下,讀取到的值不一樣。

1》如果隔離級別是讀未提交(Read-Uncommited),兩次讀到的數據都是20,(個人理解讀未提交,就是事務A未提交的修改都可以讀到)

2》如果隔離級別是讀已提交(Read-Committed),第一次讀取到的數據是10,第二次讀取到的數據是20(我個人理解讀已提交,就是只有事務A已提交的修改才可以讀到)

3》如果隔離級別是可重復度(Repeatable-Read),兩次讀到的數據都是20(我個人有理解,讀已提交就是事務B有一個很強的隔離性,只要在同一事務內,讀到的數據都是相同的)

 

  • 當執行查詢SQL時,會生成一致性視圖叫【read-view】,它由執行查詢時所未提交事務id數組(數組里最小的事務id為【min_id】和已創建的最大事務id為【max_id】組成),
  • 查詢的數據結果要跟【read-view】做比較,從而得到快照結果。話不多少,直接上個案例:

事務1 事務2 事務3 事務4
update table set name = 'A' where id  = 1      
  update table set name = 'B' where id  = 1    
  commit update table set name = 'C' where id  = 1  
update table set name = 'C' where id  = 1     select name from table where id  = 1 ; read-view:[1,3] 3
    commit  
commit     select name from table where id  = 1 

 

Undo日志如下:

 

事務4在第一次查詢過程是這樣:

1》先比對【undo_log①】,事務id為1,read-view為[1,3] 3,不符合條件,繼續向下比對;
2》比對【undo_log②】,事務id為3,事務id > 事務的最大id,所以也不可讀;
3》比對【undo_log③】,事務id為2,最小id <= 事務id <= 事務的最小id,並且不在未提交事務id數組中,所以可以,所以查詢出來的【name = B】;
我們可以根據表格看出,事務2已提交,所以結果就應該B,正確。

 

  • 讀已提交是如何使用【MVCC】實現的呢?

每次查詢的時候生成一個新的【read-view】,然后去【undo】日志中尋找符合結果的一條數據。

所以事務4對應的【read-view】應該為:[1] 3,第二次查詢【name = 'C'】

 

  • 可重復讀是如何使用【MVCC】實現的呢?

因為每次查詢的時候都會生成一個新的【read-view】,但是如果是可重復讀的時候,

第一次查詢的時候生成一個【read-view】,后面查詢的時候便會復用第一次的【read-view】,然后找出一個可讀的數據

所以事務4對應的【read-view】應該為:[1,3] 3,第二次查詢【name = 'B'】

 

  • 不過可串行化又是如何實現的呢?

串行化會在讀取的每一行數據上都加鎖(這個意思是部分鎖,但不會鎖表)

串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

 


免責聲明!

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



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