MySQL數據庫事務各隔離級別加鎖情況--read committed && MVCC


之前已經轉載過幾篇相關的文章,此次基於mysql 5.7 版本,從測試和源碼角度解釋一下RR,RC級別為什么看到的數據不一樣

先補充一下基礎知識

基本知識

假設對於多版本(MVCC)的基礎知識,有所了解。InnoDB為了實現多版本的一致讀,采用的是基於回滾段的協議。

行結構

InnoDB表數據的組織方式為主鍵聚簇索引。由於采用索引組織表結構,記錄的ROWID是可變的(索引頁分裂的時候,Structure Modification Operation,SMO),因此二級索引中采用的是(索引鍵值, 主鍵鍵值)的組合來唯一確定一條記錄。

無論是聚簇索引,還是二級索引,其每條記錄都包含了一個DELETED BIT位,用於標識該記錄是否是刪除記錄。除此之外,聚簇索引記錄還有兩個系統列:DATA_TRX_ID,DATA_ROLL_PTR。DATA _TRX_ID表示產生當前記錄項的事務ID;

DATA _ROLL_PTR指向當前記錄項的undo信息。

 

開啟4個mysql客戶端,client1 用來查看數據情況 , client2,client3,client4 更新數據

表結構

 

所有client 啟動事務

  執行 show engine innodb status\G  , 觀察目前的事務信息

這里可以看到目前沒有任何活動事務(select 不產生任何活動事務,只有insert ,update,delete 才會產生活動事務)

我們先在client2 執行一個insert sql,然后再在client1 看事務信息

 

我們可以看到client2 產生了12654 的活動事務, 我們繼續再client3執行sql

client3 產生了一個12659的事務

我們從截圖的角度看這2個事務

12659    -- 這是物理位置比較高的事務, mysql 本身里有專有名詞叫 low_limit_id ,高水位

12654    --這是物理位置比較低的事務, up_limit_id ,低水位

 

接下來我們在client1 執行select查詢

 

client2,client3還沒有提交,這時候client1 只能獲取到以前的舊數據

 

這時候client2,client3提交,再在client1查詢

重點來了,這時候mysql產生了一份快照,這里叫read_view, 快照的結構是

read_view->creator_trx_id = 當前client1的事務id;

read_view->up_limit_id = 12654;

read_view->low_limit_id = 12659;

read_view->trx_ids = [12654,12659];

read_view->m_trx_ids = 2;

 

接下來,我們在client4執行insert操作,並馬上commit提交,然后再在client1執行select查詢

 

我們可以看到client4的修改雖然已經提交,但是client1還是看不到這個變化,那是因為:

low_limit_id;    /* 索引數據事務號 DATA_TRX_ID >= low_limit_id的記錄,對於當前Read View都是不可見的 */

up_limit_id;    /* 索引數據事務號  DATA_TRX_ID< up_limit_id ,對於當前Read View都是可見的 */

 

剛才client4修改的時候產生的事務id是比12659還要大的一個數字, 沒有查看,不知道具體數字,我們假設是12700這個數字

當產生read-view的時候, low_limit_id 是 12659,up_limit_id 是12654, 12700>12659 & 12654, 所以這些12654,12659對於那個read-view來說是看不見的

 

如果在client1 select 產生read-view 之前就執行client4的修改(和提交, 這時候client4的事務id, 我們假設就是一個比12654小的數字,如12600),12600<12654, 所以client4的修改對於當前read-view就是可視的

我們看看源碼 read0types.h

 

 

那為什么事務隔離級別是RC級別的時候,重復上面的操作步驟, client1在client2,client3提交后select 的時候,就能馬上查詢到修改

我們看源碼

ha_innodb.cc的ha_innobase::external_lock方法里

在RC級別的時候,每次都會關閉read-view並產生一份新的

 


免責聲明!

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



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