<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          什么是 MVCC

          共 1991字,需瀏覽 4分鐘

           ·

          2020-08-25 21:55

          文 |?豆豆

          來源:Python 技術「ID: pythonall」


          上一篇文章我們說到數(shù)據(jù)庫的四種事務隔離級別,可以通過加鎖的方式來實現(xiàn),只是效率太低,事實上,MySQL 是通過 MVCC(多版本并發(fā)控制)來實現(xiàn)的。

          具體原理有一點點復雜,需要你用點心才能看懂,今天我們就以「可重復讀隔離級別」為例來詳細說明其具體原理。

          假設數(shù)據(jù)庫有如下記錄。

          我們都知道 InnoDB 引擎下,每一個事務都有一個事務 ID,叫做 transaction id,是在事務開始時系統(tǒng)自動分配的,且該 id 是遞增的。同時這個 id 也會記錄在數(shù)據(jù)行上面。言外之意就是數(shù)據(jù)庫表的每行記錄是有多個版本的,用事務 ID 來標示這行記錄是屬于哪個事務操作的。既然是有多個版本,那怎么拿到舊版本的數(shù)據(jù)記錄呢,答案就是在添加一個指針,指向前一個事務 ID 標識的記錄。

          而這個指針就是我們通常訴所說的 undo log,事實上,舊版本的行記錄都不是物理存在的,而是通過 undo log 實時計算出來的。

          一致性視圖

          好了,了解了行記錄事務 ID 和回滾指針的概念之后,我們來看看一致性視圖。

          當在一個事務 A 中查詢數(shù)據(jù)時,只需要確定行記錄的數(shù)據(jù)版本是否在事務 A 啟動之前生成的即可,如若是,則可見;否則不可見,則需通過回滾指針找到上一個版本來繼續(xù)判斷屬否可見,

          因此,就需要在事務啟動時,為該事務構(gòu)造一個事務數(shù)組,用來保存該事務啟動瞬間,系統(tǒng)中正在活躍的所有事務 ID,也就是啟動了但還未提交的事務 ID。

          數(shù)組中的最小值我們簡記為低位,系統(tǒng)中的最大事務 ID 記錄為高位,正是這個高位和視圖數(shù)組組成了我們說的「一致性視圖」。

          因此,對于任何一個事務 A 來說,任何數(shù)據(jù)版本的可見行都可以通過一致性視圖來得到。

          1. 如果數(shù)據(jù)版本小于低位,說明是已經(jīng)提交的記錄,則可見。
          2. 如果大于高位,說明是由未來的事務生成的,則不可見。
          3. 如果在高位和低位之間:
            1. 若在數(shù)組中,說民該事務還未提交,則不可見,
            2. 如果不在數(shù)組中,說明該事務是已經(jīng)提交了的,則可見。

          實戰(zhàn)分析

          我們針對上圖的數(shù)據(jù)記錄,假設有以下三個事務,我們來具體分析下,其一致性視圖是怎么樣的。

          假設(1,1)這行記錄的事務 ID 是 90;事務 A 開啟前,系統(tǒng)里面只有一個活躍的事務,ID = 99;事務 A、B、C 的版本號分別是 100、101、102。

          現(xiàn)在,事務 A、B、C 的視圖數(shù)組和高位分別是[99,100]/101,[99,100,101]/102,[99,100,101,102]/103。

          你要知道,讀取數(shù)據(jù)是從當前版本往前讀的,對于事務 A 來說:

          1. 當讀取到 (1,3) 的時候,事務 ID = 101,高于高位,不可見。
          2. 往前讀取歷史版本(1,2),事務 ID = 102,高于高位,不可見。
          3. 繼續(xù)往前讀取歷史版本(1,1),事務 ID = 90,低于低位,可見。

          這樣,我們就通過一致性視圖和事務 ID 找到了可見的數(shù)據(jù)版本,不論事務 A 是什么時候查詢的,看到的記錄都是一致的。

          讀提交

          上面我們分析了可重復讀隔離級別下的一致性視圖,那么在讀取提交的隔離級別下,又是怎么樣的呢?

          事實上,他們最主要的區(qū)別就是一致性視圖的創(chuàng)建時間不一樣,對于可重復讀隔離級別,一致性視圖是在事務開啟時刻生成的,之后在該事務中的查詢都共用這個一個視圖。而對于讀提交隔離級別,每一個語句執(zhí)行前都會生成一個新的視圖。

          因此,事務 A、B、C 的視圖數(shù)組和高位分別是[99,100,101]/103,[99,101]/103,[99,102]/103。

          對于事務 A 來說:

          1. 當讀取到 (1,3) 的時候,事務 ID = 101,在數(shù)組中,不可見。
          2. 往前讀取歷史版本(1,2),事務 ID = 102,不在數(shù)組中,可見。

          總結(jié)

          今天我們學習了 MVCC(多版本并發(fā)控制)的底層實現(xiàn)方式,雖然過程略顯復雜,但這保證了在不加鎖的情況下,保證了可重復讀,和讀提交。讀寫不互相干擾,能極大的提高并發(fā)能力。

          別看上面的分析步驟較復雜,事實上我們只需要記住以下兩條規(guī)則即可。在可重復讀隔離級別下,查詢只能看到在事務啟動前已經(jīng)提交的數(shù)據(jù)。在讀提交隔離級別下,查詢只能看到在語句啟動前已經(jīng)提交的數(shù)據(jù)。

          參考

          極客時間 「MySQL實戰(zhàn)45講 08節(jié)」。


          PS公號內(nèi)回復「Python」即可進入Python 新手學習交流群,一起 100 天計劃!


          老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點一下,如果感覺文章內(nèi)容不錯的話,記得分享朋友圈讓更多的人知道!

          代碼獲取方式

          識別文末二維碼,回復:python

          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久一区二区三区四区六区 | 久久蜜桃视频 | 国产一级特A片 | 成人电影一二三区 | 乱伦亚洲色國片 |