圖說Mysql的MVCC原理


一.什么是MVCC

  MVCC,全稱Multi-Version Concurrency Control,即多版本並發控制。MVCC是一種並發控制的方法,一般在數據庫管理系統中,實現對數據庫的並發訪問,在編程語言中實現事務內存。
  MVCC在MySQL InnoDB中的實現主要是為了提高數據庫並發性能,用更好的方式去處理讀-寫沖突,做到即使有讀寫沖突時,也能做到不加鎖,非阻塞並發讀。
 

二.一個小Demo

  下面我們來看一個小demo,我這里新建來一張表mvcc_test,表字段有id和num。這里插入一筆數據 id=1 num=12

  現在我們假設有3個事務,按以下順序執行(如下圖):

  1. 開啟事務A
  2. 開啟事務B
  3. 執行事務A查詢
  4. 執行事務B查詢
  5. 執行事務C
  6. 執行事務B更新
  7. 執行事務B查詢
  8. 執行事務A查詢

   那么請問步驟7和8執行的結果的num分別是多少?

 

   答案是:14和12

  我們偉大的小平同志曾經說過:“實踐是檢驗真理的唯一標准”,這里我們實際來操作一下試試!!! 
  我用navicat分別建來三個查詢
事務A:                                                                                                                                
     
事務B:
  
事務C: 
 

    下面我們按照操作步驟執行

   步驟1 ——開啟事務A

   

   步驟2——開啟事務B

       

    步驟3——執行查詢A

   

    步驟4——執行查詢B

         

      步驟5——執行事務C

         

      步驟6——執行事務B更新

        

    步驟7——執行事務B查詢

   

    步驟8——執行事務A查詢並commit

    

    很神奇對吧,下面我們就談談它的原理。   

  

 三.圖說原理

  首先了解MVCC里面2個重要概念

  快照讀和當前讀

     快照讀:像不加鎖的select操作就是快照讀,即不加鎖的非阻塞讀;快照讀的前提是隔離級別不是串行級別,串行級別下的快照讀會退化成當前讀;

      當前讀:就是它讀取的是記錄的最新版本,讀取時還要保證其他並發事務不能修改當前記錄,會對讀取的記錄進行加鎖。

  InnerDB的事務管理

    事務ID和順序遞增

   

   在mysql的每一行數據中有3個隱藏字段

  • DB_TRX_ID
    6byte,最近修改(修改/插入)事務ID:記錄創建這條記錄/最后一次修改該記錄的事務ID
  • DB_ROLL_PTR
    7byte,回滾指針,指向這條記錄的上一個版本(存儲於rollback segment里)
  • DB_ROW_ID
    6byte,隱含的自增ID(隱藏主鍵),如果數據表沒有主鍵,InnoDB會自動以DB_ROW_ID產生一個聚簇索引

 

  假設我們現在表中數據id=1的事務id=100

    

   在執行步驟1和2之后,由於事務的順序遞增特性,事務A的事務id=101,事務B的id=102

   在執行步驟3的時候因為是查詢,所以會生成一個num=12的快照,進行快照讀,步驟4同理

   在執行步驟5時候,因為是更新操作,進行當前讀,事務C會創建一個新事務,事務id=103,並修改當前最新版本DB_TRX_ID=103,num變成13

       

   此時執行步驟6,進行當前讀,事務B讀取讀DB_TRX_ID不是100,而是103,讀取到num為13進行更新操作,num變成14

  

   執行步驟7查詢,進行快照讀還是事務A開啟時候讀快照所以num結果還是12。

   執行步驟8查詢,因為在事務B中我們進行最后的更新操作,所以可以返回最新的num值14。

 
 


免責聲明!

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



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