您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關MVCC中快照怎么工作的,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
在 MySQL 中(innodb存儲引擎),實際上每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態的值。
假設一個值從 1 被按順序改成了 2、3、4,在回滾日志里面就會有類似下面的記錄。
當前值是 4,但是在查詢這條記錄的時候,不同時刻啟動的事務會有不同的 read-view。如圖中看到的,在視圖 A、B、C 里面,這一個記錄的值分別是 1、2、4,同一條記錄在系統中可以存在多個版本,就是數據庫的多版本并發控制(MVCC)。對于 read-view A,要得到 1,就必須將當前值依次執行圖中所有的回滾操作得到。
InnoDB 里面每個事務有一個唯一的事務 ID,叫作 transaction id。它是在事務開始的時候向 InnoDB 的事務系統申請的,是按申請順序嚴格遞增的。
而每行數據也都是有多個版本的。每次事務更新數據的時候,都會生成一個新的數據版本,并且把 transaction id 賦值給這個數據版本的事務 ID,記為 row trx_id。同時,舊的數據版本要保留,并且在新的數據版本中,能夠有信息可以直接拿到它。
也就是說,數據表中的一行記錄,其實可能有多個版本 (row),每個版本有自己的 row trx_id。
按照可重復讀的定義,一個事務啟動的時候,能夠看到所有已經提交的事務結果。但是之后,這個事務執行期間,其他事務的更新對它不可見。
因此,一個事務只需要在啟動的時候聲明說,“以我啟動的時刻為準,如果一個數據版本是在我啟動之前生成的,就認;如果是我啟動以后才生成的,我就不認,我必須要找到它的上一個版本”。當然,如果“上一個版本”也不可見,那就得繼續往前找。還有,如果是這個事務自己更新的數據,它自己還是要認的。
在實現上, InnoDB 為每個事務構造了一個數組,用來保存這個事務啟動瞬間,當前正在“活躍”的所有事務 ID。“活躍”指的就是,啟動了但還沒提交。
數組里面事務 ID 的最小值記為低水位,當前系統里面已經創建過的事務 ID 的最大值加 1 記為高水位。
這個視圖數組把所有的 row trx_id 分成了幾種不同的情況。
這樣,對于當前事務的啟動瞬間來說,一個數據版本的 row trx_id,有以下幾種可能:
如果落在綠色部分,表示這個版本是已提交的事務或者是當前事務自己生成的,這個數據是可見的;
如果落在紅色部分,表示這個版本是由將來啟動的事務生成的,是肯定不可見的;
如果落在黃色部分,那就包括兩種情況
a. 若 row trx_id 在數組中,表示這個版本是由還沒提交的事務生成的,不可見;
b. 若 row trx_id 不在數組中,表示這個版本是已經提交了的事務生成的,可見。
舉個例子:
session A 啟動了一個事務A, 在事務 A 開始前,系統里面分別有三個活躍事務,ID分別 是90 93 95 。
那么事務A的ID是100
此時對于事務A的視圖數組是這樣的 【90 93 95 100】,其中 低水位是 90, 高水位是100+1=101;
現在事務A開始讀數據了
假如讀到了ID是104的,大于高水位101,表示這個版本是由將來啟動的事務生成的,是肯定不可見的;
讀到了ID是88的,小于低水位90,表示這個版本是已提交的事務或者是當前事務自己生成的,這個數據是可見的;
讀到了ID是94的,在低水位和高水位之間,但是不在【90 93 95 100】這個數組里,表示這個版本是已經提交了的事務生成的,可見。
讀到了ID是93的,在低水位和高水位之間,這【90 93 95 100】這個數組里,表示這個版本是由還沒提交的事務生成的,不可見;
這個判斷規則是從代碼邏輯直接轉譯過來的,但是正如你所見,用于人肉分析可見性很麻煩。
所以,我來給你翻譯一下。一個數據版本,對于一個事務視圖來說,除了自己的更新總是可見以外,有三種情況:
版本未提交,不可見;
版本已提交,但是是在視圖創建后提交的,不可見;
版本已提交,而且是在視圖創建前提交的,可見。
關于“MVCC中快照怎么工作的”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。