淺析MVCC中的快照,看看快照是怎么工作的?

本篇文章帶大家了解mvcc中的快照,看看快照在mvcc中是怎么工作的?希望能夠給大家提供幫助!

淺析MVCC中的快照,看看快照是怎么工作的?

MVCC

mysql 中(innodb存儲引擎),實際上每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態(tài)的值。

假設(shè)一個值從 1 被按順序改成了 2、3、4,在回滾日志里面就會有類似下面的記錄。

淺析MVCC中的快照,看看快照是怎么工作的?

當前值是 4,但是在查詢這條記錄的時候,不同時刻啟動的事務(wù)會有不同的 read-view。如圖中看到的,在視圖 A、B、C 里面,這一個記錄的值分別是 1、2、4,同一條記錄在系統(tǒng)中可以存在多個版本,就是數(shù)據(jù)庫的多版本并發(fā)控制(MVCC)。對于 read-view A,要得到 1,就必須將當前值依次執(zhí)行圖中所有的回滾操作得到。

InnoDB 是怎么定義一個 ‘快照’

InnoDB 里面每個事務(wù)有一個唯一的事務(wù) ID,叫作 transaction id。它是在事務(wù)開始的時候向 InnoDB 的事務(wù)系統(tǒng)申請的,是按申請順序嚴格遞增的。

而每行數(shù)據(jù)也都是有多個版本的。每次事務(wù)更新數(shù)據(jù)的時候,都會生成一個新的數(shù)據(jù)版本,并且把 transaction id 賦值給這個數(shù)據(jù)版本的事務(wù) ID,記為 row trx_id。同時,舊的數(shù)據(jù)版本要保留,并且在新的數(shù)據(jù)版本中,能夠有信息可以直接拿到它。

也就是說,數(shù)據(jù)表中的一行記錄,其實可能有多個版本 (row),每個版本有自己的 row trx_id。

淺析MVCC中的快照,看看快照是怎么工作的?

按照可重復(fù)讀的定義,一個事務(wù)啟動的時候,能夠看到所有已經(jīng)提交的事務(wù)結(jié)果。但是之后,這個事務(wù)執(zhí)行期間,其他事務(wù)的更新對它不可見。

因此,一個事務(wù)只需要在啟動的時候聲明說,“以我啟動的時刻為準,如果一個數(shù)據(jù)版本是在我啟動之前生成的,就認;如果是我啟動以后才生成的,我就不認,我必須要找到它的上一個版本”。當然,如果“上一個版本”也不可見,那就得繼續(xù)往前找。還有,如果是這個事務(wù)自己更新的數(shù)據(jù),它自己還是要認的。

在實現(xiàn)上, InnoDB 為每個事務(wù)構(gòu)造了一個數(shù)組,用來保存這個事務(wù)啟動瞬間,當前正在“活躍”的所有事務(wù) ID。“活躍”指的就是,啟動了但還沒提交。

數(shù)組里面事務(wù) ID 的最小值記為低水位,當前系統(tǒng)里面已經(jīng)創(chuàng)建過的事務(wù) ID 的最大值加 1 記為高水位。

這個視圖數(shù)組把所有的 row trx_id 分成了幾種不同的情況。

淺析MVCC中的快照,看看快照是怎么工作的?

這樣,對于當前事務(wù)的啟動瞬間來說,一個數(shù)據(jù)版本的 row trx_id,有以下幾種可能:

  • 如果落在綠色部分,表示這個版本是已提交的事務(wù)或者是當前事務(wù)自己生成的,這個數(shù)據(jù)是可見的;

  • 如果落在紅色部分,表示這個版本是由將來啟動的事務(wù)生成的,是肯定不可見的;

  • 如果落在黃色部分,那就包括兩種情況

a. 若 row trx_id 在數(shù)組中,表示這個版本是由還沒提交的事務(wù)生成的,不可見;b. 若 row trx_id 不在數(shù)組中,表示這個版本是已經(jīng)提交了的事務(wù)生成的,可見。

舉個例子:

Session A 啟動了一個事務(wù)A, 在事務(wù) A 開始前,系統(tǒng)里面分別有三個活躍事務(wù),ID分別 是90 93 95 。
那么事務(wù)A的ID是100
此時對于事務(wù)A的視圖數(shù)組是這樣的 【90 93 95 100】,其中 低水位是 90, 高水位是100+1=101;
現(xiàn)在事務(wù)A開始讀數(shù)據(jù)了

  • 假如讀到了ID是104的,大于高水位101,表示這個版本是由將來啟動的事務(wù)生成的,是肯定不可見的;
  • 讀到了ID是88的,小于低水位90,表示這個版本是已提交的事務(wù)或者是當前事務(wù)自己生成的,這個數(shù)據(jù)是可見的;
  • 讀到了ID是94的,在低水位和高水位之間,但是不在【90 93 95 100】這個數(shù)組里,表示這個版本是已經(jīng)提交了的事務(wù)生成的,可見。
  • 讀到了ID是93的,在低水位和高水位之間,這【90 93 95 100】這個數(shù)組里,表示這個版本是由還沒提交的事務(wù)生成的,不可見;

這個判斷規(guī)則是從代碼邏輯直接轉(zhuǎn)譯過來的,但是正如你所見,用于人肉分析可見性很麻煩。

所以,我來給你翻譯一下。一個數(shù)據(jù)版本,對于一個事務(wù)視圖來說,除了自己的更新總是可見以外,有三種情況:

  • 版本未提交,不可見;

  • 版本已提交,但是是在視圖創(chuàng)建后提交的,不可見;

  • 版本已提交,而且是在視圖創(chuàng)建前提交的,可見。

【相關(guān)推薦:mysql視頻教程

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊13 分享