MVCC的實現原理
了解實現原理之前,先理解下面幾個組件的內容
1、 當前讀和快照讀
先普及一下什么是當前讀和快照讀。
當前讀:讀取數據的最新版本,并對數據進行加鎖。
例如:insert、update、delete、select for update、 select lock in share mode。
快照讀:讀取數據的歷史版本,不對數據加鎖。
例如:select
最重要概念: MVCC原理是基于Undo Log、隱藏字段、Read View(讀視圖)實現的。
2、隱藏字段
MySQL的隱藏字段,當我們創建一張表時,InnoDB引擎會增加3個隱藏字段。
- DB_TRX_ID(最近一次提交事務的ID):修改表數據時,都會提交事務,每個事務都有一個唯一的ID,這個字段就記錄了最近一次提交事務的ID。
- DB_ROLL_PTR(上個版本的地址):修改表數據時,舊版本的數據都會被記錄到Undo Log日志中,每個版本的數據都有一個版本地址。這個字段記錄的就是上個版本的地址。
- DB_ROW_ID(隱藏主鍵):如果表中沒有主鍵會默認生成該隱藏主鍵。
3、Undo log版本鏈
Undo log日志詳解:主要被用到了快照讀這一個階段
undo log版本鏈示意圖:
過程:
- 第一次事務進行更新數據時候,首先會在 undo log版本鏈 記錄原來數據的舊版本,以及該版本的指針,然后進行更新操作,此時會修改DB_TRX_ID為最近一次修改數據的事務ID,DB_ROLL_PTR指向上一次版本數據的指針,這樣不斷有事務更新該數據時候,表記錄和 undo log 歷史數據就組成了一個版本鏈。
4、Read View(讀視圖)
在事務中,執行SQL查詢,就會生成一個讀視圖,它是快照讀 SQL執行時MVCC提取數據的依據,記錄并維護系統當前活躍的事務 id
快照讀一般是讀取的歷史版本的讀視圖, 當前圖 會生成一個最新版本的讀視圖。
讀視圖是基于下面幾個字段實現的:
-
m_ids:當前系統中活躍的事務ID集合,即未提交的事務ID集合。
-
min_trx_id:m_ids中最小的ID
-
max_trx_id:下一個要分配的事務ID
-
creator_trx_id: 當前事務ID
讀視圖決定當前事務能讀到哪個版本的數據,從表記錄到 Undo Log 歷史數據的版本鏈,依次匹配,滿足哪個版本的匹配規則,就能讀到哪個版本的數據,一旦匹配成功就不再往下匹配。
數據可見性規則:
當一個匹配可以訪問該數據的時候就可以進行數據提取了,也就是直接返回查詢數據
5、不同隔離級別下可見性分析
在不同的事務隔離級別下,生成讀視圖的規則不同:
READ COMMITTED(讀已提交) :在事務中每一次執行快照讀時都生成一個讀視圖,每個讀視圖中四個字段的值都是不同的。
REPEATABLE READ(可重復讀) :僅在事務中第一次執行快照讀時生成讀視圖,后續復用這個讀視圖。