Mysql知識延展(七)MVCC多版本併發控制

MVCC簡述

MVCC(Mutil-Version Concurrency Control),就是多版本併發控制。MVCC 是一種併發控制的方法,一般在數據庫管理系統中,實現對數據庫讀寫的併發訪問

在Mysql的InnoDB引擎中就是指在已提交讀(READ COMMITTD)可重複讀(REPEATABLE READ)這兩種隔離級別下的事務對於SELECT操作會訪問版本鏈中的記錄的過程。這就使得別的事務可以修改這條記錄,反正每次修改都會在版本鏈中記錄SELECT可以去版本鏈中讀取記錄,這就實現了讀-寫,寫-讀的併發執行,提升了系統的性能。

當前讀和快照讀

在MVCC併發控制中,讀操作可以分成兩類:

  • 快照讀 (snapshot read)
    讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。簡單的select操作,屬於快照讀。
  • 當前讀 (current read)
    讀取的是記錄的最新版本,並且當前讀返回記錄,都會加上鎖,保證其他事務不會再併發修改這
    條記錄。插入/更新/刪除操作,屬於當前讀。
    在這裏插入圖片描述

一致性非鎖定讀

一致性非鎖定讀(consistent nonlocking read)是指InnoDB存儲引擎通過多版本控制(MVCC)讀取當前數
據庫中行數據的方式
如果讀取的行正在執行DELETE或UPDATE操作,這時讀取操作不會因此去等待行鎖的釋放。相反地,InnoDB會去讀取行的一個最新可見快照
在這裏插入圖片描述
若出現AB會話如下圖所示:
在這裏插入圖片描述
當會話B提交事務後,會話A再次運行 SELECT * FROM test WHERE id = 1 的SQL語句
時,兩個不同的事務隔離級別下得到的結果可能就不一樣了。

Mysql實現MVCC依賴undo log以及read view

版本鏈

InnoDB引擎表中,它的聚簇索引記錄中有兩個必要的隱藏列

  • trx_id
    這個id用來存儲的每次對某條聚簇索引記錄進行修改的時候的事務id
  • roll_pointer
    每次對哪條聚簇索引記錄有修改的時候,都會把老版本寫入undo日誌中。這個roll_pointer就是存了一個指針,它指向這條聚簇索引記錄的上一個版本的位置,通過它來獲得上一個版本的記錄信息。(注意插入操作的undo日誌沒有這個屬性,因爲它沒有老版本)

事務鏈表

MySQL中的事務開始到提交這段過程中,都會被保存到一個叫trx_sys的事務鏈表中,這是一個基本
的鏈表結構:
ct-trx --> trx11 --> trx9 --> trx6 --> trx5 --> trx3;
事務鏈表中保存的都是還未提交的事務,事務一旦被提交,則會被從事務鏈表中摘除

  • RR隔離級別下,在每個事務開始的時候,會將當前系統中的所有的活躍事務拷貝到一個列表中(read view)
  • RC隔離級別下,在每個語句開始的時候,會將當前系統中的所有的活躍事務拷貝到一個列表中(read view)

show engine innodb status ,就能夠看到事務列表。

ReadView

ReadView中主要就是有個列表存儲我們系統中當前活躍着的讀寫事務,也就是begin了還未提交的事務。通過這個列表來判斷記錄的某個版本是否對當前事務可見。假設當前列表裏的事務id爲[80,100]。

  • 如果訪問的記錄版本的事務id爲50比當前列表最小的id80小,那說明這個事務在之前就提交了,所以對當前活動的事務來說是可訪問的
  • 如果訪問的記錄版本的事務id爲90,發現此事務在列表id最大值和最小值之間,那就再判斷一下是否在列表內,如果在那就說明此事務還未提交,所以版本不能被訪問。如果不在說明事務已經提交,所以版本可以被訪問
  • 如果訪問的記錄版本的事務id爲110,那比事務列表最大id100都大,那說明這個版本在ReadView生成之後才發生的,所以不能被訪問

這些記錄都是去版本鏈裏面找的先找最近記錄,如果最近這一條記錄事務id不符合條件,不可見的話再去找上一個版本再比較當前事務的id和這個版本事務id看能不能訪問,以此類推直到返回可見的版本或者結束

參考:https://baijiahao.baidu.com/s?id=1629409989970483292&wfr=spider&for=pc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章