你解釋一下MVCC?
mvcc的意思是多版本併發控制。指維護一個資料的多個版本,使得讀寫操作沒有衝突,
它的底層實現主要是依賴了資料庫中的三個部分,隱藏欄位,undo log日誌和readView讀檢視
隱藏欄位是指:在mysql中給每個表都設定了隱藏欄位,有一個是最近修改事務的id,記錄每一次操作的事務id,是自增的;另一個是回滾指標,指向上一個版本的事務版本記錄地址;
undo log主要的作用是記錄回滾日誌,儲存老版本資料,在內部會形成一個版本鏈,在多個事務並行操作某一行記錄,記錄不同事務修改資料的版本,透過回滾指標形成一個連結串列,連結串列頭部就是最新修改的舊記錄,尾部是最早修改的舊記錄
readView讀檢視解決的是一個事務查詢選擇版本的問題,內部定義了一些匹配規則和當前的一些事務id判斷該訪問那個版本的資料,不同的隔離級別快照讀是不一樣的,最終的訪問的結果不一樣。RC隔離級別下,每一次執行快照讀時生成ReadView,RR隔離級別僅在事務中第一次執行快照讀時生成讀檢視,後續複用該讀檢視
MVCC
多版本併發控制。指維護一個資料的多個版本,使得讀寫操作沒有衝突
多個事物併發的情況下到底該訪問哪個版本
底層實現
-
隱藏欄位:
- trx_id(事務id),記錄每一次操作的事務id,是自增的
- roll_pointer(回滾指標),指向上一個版本的事務版本記錄地址
- row_id,隱藏主鍵
-
undo log:
- 回滾日誌,儲存老版本資料
- 版本鏈:多個事務並行操作某一行記錄,記錄不同事務修改資料的版本,透過roll pointer指標形成一個連結串列
-
readView解決的是一個事務查詢選擇版本的問題
-
根據readView的匹配規則和當前的一些事務id判斷該訪問那個版本的資料
-
不同的隔離級別快照讀是不一樣的,最終的訪問的結果不一樣
- RC:每一次執行快照讀時生成ReadView
- RR:僅在事務中第一次執行快照讀時生成ReadView,後續複用
-
undo log
回滾日誌,在insert、update、delete時產生的便於資料回滾的日誌
insert產生的undo log只在回滾時需要,事物提交後可立即被刪除
update、delete產生的日誌不僅在回滾時需要,MVCC版本訪問也需要,不會被立即刪除
不同事物或相同事物對同一條記錄進行修改,會導致該記錄的undo log生成一條記錄版本鏈,連結串列頭部是最新的舊記錄,連結串列尾部是最早的舊記錄
ReadView
讀檢視,是快照讀SQL執行時MVCC提取資料的依據,記錄並維護系統當前活躍的事物未提交的id
其中
- Read Committed:RC隔離級別下每次select都生成一個快照讀
- Repeatable Read:RR隔離級別下,開啟事物後的第一個select才是快照讀
ReadView包含四個核心欄位:
欄位 | 含義 |
---|---|
m_ids | 當前活躍的事務ID集合 |
min_trx_id | 最小活躍事務ID |
max_trx_id | 預分配事務ID,當前最大事務ID+1(因為事務ID是自增的) |
creator_trx_id | ReadView建立者的事務ID |
版本鏈資料訪問規則
trx_id: 代表是當前事務ID。
- trx_id == creator_trx_id?---->可以訪問該版本--------->說明資料是當前這個事務更改的。
- trx_id < min_trx_id?---->可以訪問該版本--------->成立,說明資料已經提交了。
- trx_id >max_trx_id?---->不可以訪問該版本--------->成立,說明該事務是在ReadView生成後才開啟。
- min_trx_id <= trx_id <= max_trx_id? ---->如果trx_id不在m_ids中是可以訪問該版本的---->成立,說明資料已經提交。
一個一個比,有一個成立就可以讀到
不同隔離級別下,生成ReadView的時機不同
- RC隔離級別下,在事物中每一次執行快照讀時生成ReadView
- RR隔離級別下,記載事物中第一次執行快照讀時生成ReadView,後續複用該ReadView
當前讀
讀取的是記錄的最新版本,讀取時還要保證其他併發事物不能修改當前記錄,會對讀取的記錄進行加鎖
一般的日常操作select(共享鎖)、update、insert、delete(排他鎖)都是一種當前讀
快照讀
讀取的是記錄資料的可見版本,有可能是歷史資料,不加鎖,是非阻塞讀
簡單的select不加鎖就是快照讀