InnoDB事務實現(xiàn)原理-MVCC

InnoDB 一共支持四種等級的事務:

  • 讀未提交
  • 讀以提交
  • 可重復讀
  • 串行化

其中讀未提交實現(xiàn)最簡單,每次讀最新的記錄即可。而串行化則是通過加鎖完成的。其中讀已提交和讀未提交是通過 MVCC 實現(xiàn)的,其基本原理都相同。

版本鏈

對于使用InnoDB存儲引擎的表來說,它的聚簇索引記錄中都包含兩個必要的隱藏列:

  • trx_id:每次一個事務對某條聚簇索引記錄進行改動時,都會把該事務的事務 id 賦值給 trx_id 隱藏列。
  • roll_pointer:每次對某條聚簇索引記錄進行改動時,都會把舊的版本寫入到undo日志中,然后這個隱藏列就相當于一個指針,可以通過它來找到該記錄修改前的信息。

同樣,undo log 中也存在 trx_id 以及 roll_pointer 指針。roll_pointer 指向該 undo log 上一個版本的 undo log。因此修改的記錄根據(jù) roll_pointer 就形成了鏈表,這條鏈表中的所有值就是形成了版本鏈。

ReadView

ReadView 是實現(xiàn)讀以提交和可重復度的實現(xiàn)方式。其實現(xiàn)原理,則是對于查詢的字段,尋找其版本鏈上對當前 ReadView 的版本。例如,讀已提交隔離等級下,未提交的事務所修改產(chǎn)生版對當前 ReadView 就是就是不可見的。

ReadView 中包含四個比較重要的概念:

  • m_ids:表示在生成ReadView時當前系統(tǒng)中活躍的讀寫事務的事務id列表。
  • min_trx_id:表示在生成ReadView時當前系統(tǒng)中活躍的讀寫事務中最小的事務id,也就是m_ids中的最小值。
  • max_trx_id:表示生成ReadView時系統(tǒng)中應該分配給下一個事務的id值。
    小貼士: 注意max_trx_id并不是m_ids中的最大值,事務id是遞增分配的。比方說現(xiàn)在有id為1,2,3這三個事務,之后id為3的事務提交了。那么一個新的讀事務在生成ReadView時,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。
  • creator_trx_id:表示生成該ReadView的事務的事務id。

有了這個ReadView,這樣在訪問某條記錄時,只需要按照下邊的步驟判斷記錄的某個版本是否可見:

  • 如果被訪問版本的trx_id屬性值與ReadView中的creator_trx_id值相同,意味著當前事務在訪問它自己修改過的記錄,所以該版本可以被當前事務訪問。
  • 如果被訪問版本的trx_id屬性值小于ReadView中的min_trx_id值,表明生成該版本的事務在當前事務生成ReadView前已經(jīng)提交,所以該版本可以被當前事務訪問。
  • 如果被訪問版本的trx_id屬性值大于或等于ReadView中的max_trx_id值,表明生成該版本的事務在當前事務生成ReadView后才開啟,所以該版本不可以被當前事務訪問。
  • 如果被訪問版本的trx_id屬性值在ReadView的min_trx_id和max_trx_id之間,那就需要判斷一下trx_id屬性值是不是在m_ids列表中,如果在,說明創(chuàng)建ReadView時生成該版本的事務還是活躍的,該版本不可以被訪問;如果不在,說明創(chuàng)建ReadView時生成該版本的事務已經(jīng)被提交,該版本可以被訪問。

讀已提交以及可重復讀實現(xiàn)的方式只是生成 ReadView 時機不同:

  • 讀已提交: 每次 select 時都會生成 ReadView
  • 可重復讀: 只在事務開啟時生成一次 ReadView
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容