MVCC是不加鎖實現多個事務對數據庫的併發訪問
淺顯原理:
在每一行除了本來的數據外附加了兩列,一列是創建行時的版本號ID一列是刪除時的版本號ID
id | name | create-version | delete-version |
---|---|---|---|
1 | tom |
- 如果現在事務ID爲1的事務插入了一行數據就會有
id | name | create-version | delete-version |
---|---|---|---|
1 | tom |
將createversion修改爲當前的事務id
- 如果現在事務ID爲2的事務改了id = 1的name
id | name | create-version | delete-version |
---|---|---|---|
1 | tom | 1 | 2 |
1 | mike | 2 |
會把之前的刪除版本號填上自己的,並且代替原來的創建版本號
查詢過濾條件:
-
只有創建版本號小於或等於當前事務id,即事務id爲2的事務只能讀取到create version<=2的已提交的事務的數據集
-
刪除版本號未指定,或者刪除版本號大於當前事務id,就是說當前事務時,確保這個數據沒有被刪除。
底層原理(複雜原理)
首先在每個事務對數據庫某一行進行修改的時候,在這一行上還會有附加的事務id(DB_TRX_ID)和回滾指針(DB_ROLL_PTR)
(先不用管隱式主鍵不重要)
當我們事務對數據庫進行修改的時候,新的回滾指針指向上一次的版本,把老的放到undo日誌裏面,這樣就會形成一條版本引用鏈
如下圖
我們從上到下按時間順序搞三個事務:
看select1的第一個select,因爲事務100和事務200未對account表操作,很顯然id = 1就是lilei300
再看第二次select,這時候就得用生成的readview結合一定的過濾條件去版本鏈裏面找哪個版本的lilei合適
先說readview,MVCC只適用於可重複讀和讀已提交,可重複讀是一直沿用第一次select生成的readview,讀已提交是每一次查找都生成新的readview。那麼readview是什麼呢
readview
它由未提交的事務id數組(裏面最小的事務id叫min_id)和已知的最大事務id(max_id)組成,每次都是拿這個readview按照一定的規則在版本鏈中去找哪一行數據合適,可見:
會根據min_id,max_id將整個事務版本號集合劃分爲:
版本鏈比對規則:
1.如果落在綠色部分(trx id<min id),表示個版本是已提交的事務生成的,這個數據是可見的
2.如果落在紅色部分(trx id > max_id),表示這個版本是由將來啓動的事務生成的,是肯定不可見的
3.如果落在黃色部分 max id),那就包括兩種情況
a.若row的 trx id在數組中,表示這個版本是由還沒提交的事務生成的,不可見,當前自己的事務是可見的
b.若rowtrx的 id不在數組中,表示這個版本是已經提交了的事務生成的,可見。
再來看select 1中的第二條查詢:
readview = [100,200]300;
在版本鏈中按照此規則找出lilei300