天天看點

面試必會 InnoDB的多版本并發控制(MVCC)一、開場白二、MVCC存在的意義三、MVCC如何實作讀和寫相容四、遺留問題

一、開場白

MVCC(Multi-Version Concurrency Control)即多版本并發控制,通俗講就是“通過多個版本的記錄來實作并發控制”。并發控制的定義所述者衆多,此不贅述。

實作并發控制的方法有:鎖,MVCC。這篇文化講的就是MVCC

二、MVCC存在的意義

剛才說了,實作并發控制方法有鎖和MVCC。衆所周知,如果存在兩個幹同樣事情的東西,我們都要分析對比其優劣。那麼MVCC和鎖有何優劣對比呢?再說直白一些,既然鎖可以實作并發控制,為什麼還需要MVCC呢?

因為純鎖的方式隻實作了讀-讀相容,而讀-寫,寫-讀,寫-寫都是沖突的,這就會産生較多的鎖阻塞,并發效率低。 而我們親愛的MVCC,它實作了讀-寫,寫-讀的相容,大大減少了鎖阻塞,提高了并發效率!

三、MVCC如何實作讀和寫相容

1、四個隐藏字段

列名 位元組數 含義 作用
DB_TRX_ID 6 記錄的版本号 Insert或Update行的最後一個事務的事務ID。(Delete也視為更新,并需要将其标記為已删除)
DB_ROLL_PTR 7 復原指針 指向最近的曆史資料
DB_ROW_ID 6 行隐藏主鍵 當表沒有設定主鍵時,系統自動為其設定的隐藏主鍵

還有一個删除标志,當該行被執行Delete時,将此标志設為已删除狀态,但是記錄依然存在,要等事務送出後才會删除。

2、undo log

undo log即復原日志,屬于InnoDB的事務日志。雖然叫復原日志,但是其作用卻不僅僅限于復原!

undo log記錄了曆史資料,這些曆史資料的作用是:

(1)實作復原,以保證事務的原子性

(2)實作MVCC,以實作事務的隔離性

本文隻說第二點,即undo log在MVCC中發揮的作用

 3、版本鍊

每開啟一個事務,事務會用目前的系統版本号作為自己的事務ID,并且系統版本号都會增加1。舉個例子:

想象這樣一個場景,很多人進入一個會場,會場入口有一個發号員,入場者根據自己拿到的号去對号入座。發号員的發号規則是:按照遞增順序發号!即來一個人,發1号,再來一個人,發2号,又來一個人,發3号...以此類推。這樣的結果就是,每個人拿到的号都不一樣,各自做自己的位置。(了解了這個例子隻後,就忘掉它,因為這個例子對後面的了解沒用,甚至會誤導你)

每次對記錄進行update操作時,都會把舊的記錄标記為已删除,寫入undo日志中,并且把新記錄的復原指針指向這條舊記錄,新紀錄DB_TRX_ID字段設為目前事務ID。每次修改都這樣操作,形成的版本鍊是這樣的。

面試必會 InnoDB的多版本并發控制(MVCC)一、開場白二、MVCC存在的意義三、MVCC如何實作讀和寫相容四、遺留問題

圖檔來自 這篇文章

4、MVCC中的Insert和Delete操作

上面說了MVCC中的Update操作的做法,那Insert和Delete操作是如何做的呢?

Insert操作會産生一條新的記錄,其DATA_TRX_ID字段為目前事務的ID,其DATA_ROLL_PTR字段為空。

Delete操作會将目前行标記為已删除,DATA_TRX_ID字段為目前事務的ID。

5、MVCC實作可重複讀

MVCC通過快照讀實作可重複讀,即在事務中第一條Select語句開始時生成一個ReadView,之後該事務中所有的簡單Select(沒有for update和lock in share model)都會在此ReadView上進行,并且對于傳回的記錄,必須滿足:

(1)如果沒有被标記為删除,其DATA_TRX_ID字段值小于或等于目前事務ID的記錄。當滿足此條件的記錄有多個時,選DATA_TRX_ID字段值最大的(即最近的曆史值)

(2)如果已經标記為删除,其DATA_TRX_ID字段值大于目前事務ID的記錄。

6、讀-寫相容

有了上述這些控制,在進行資料庫讀寫時,讀操作不用阻塞寫操作,寫操作不用阻塞讀操作,而且不會産生并發問題。這裡的寫操作包括:Insert,Update,Delete

如有錯誤之處,感謝指出

四、遺留問題

1、MVCC實作方式(悲觀鎖,樂觀鎖)

2、undo log的具體寫入和儲存流程