亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MVCC詳細講解

發布時間:2020-05-07 16:34:36 來源:億速云 閱讀:238 作者:Leah 欄目:MySQL數據庫
今天小編給大家分享的是MVCC的詳細介紹,相信很多人都不太了解,為了讓大家更加了解MVCC,所以給大家總結了以下內容,話不多說,一起往下看吧。
  1. MVCC的實現,是通過保存數據在某個時間點的快照來實現的,也就是說,不管需要執行多長時間,每個事務看到的數據是一致的,根據事務開始的時間不同,每個事務對同一張表,同一時刻看到的數據可能是不一樣的。
  2. innodb在基于鎖的并發控制技術上,實現了MVCC技術,innodb的MVCC技術有以下幾個特點:
    • 事務的標識,依靠事務ID,是一個全局唯一的64bits數值
    • 多版本,是元組級的多版本,而不是oracle實現的是頁面級的多版本
    • 最新的數據存儲在數據頁面中,其他數據的舊版本存儲在回滾段中
  3. 因為innodb的多版本是元組級的版本,所以在每個記錄上,有一些與并發和回滾等于事務相關的隱含字段
    • DATA_TRX_ID: 6字節長,表示上一個執行插入或更新操作的事務
    • DATA_ROLL_PTR: 7字節長,表示舊版本的數據位于回滾段中的位置,指向的是一個舊版本,只有元組被更新,才有會新版本產生,舊版本被置于回滾段,因此一致性無鎖讀操作按照“read view”快照需要讀取舊版本時,只能根據事務ID回到回滾段中尋找舊版本
    • DATA_ROW_ID:6字節長,表示執行插入操作后生成的單調自增長的行的ID標識,如果存在聚集索引,索引項則包括的是這個DB_ROW_ID值
    • DELETE_BIT: 刪除標志位
  4. 位于回滾段中的UNDO日志分為兩種
    • INSERT UNOD LOGS:插入到回滾段的日志,僅用于事務提交時使用,當事務提交,則對應的INSETR UNDO LOGS里面的內容被清除
    • UPDATE UNDO LOGS:被用于一致性無鎖讀,為一致性讀提供快照隔離下的可被讀取的老版本數據,當沒有需要滿足一致性讀的快照時,一些老版本數據才被清理
  5. MVCC的工作機制
    • innodb的MVCC,是通過在每行記錄后面保存兩個隱藏的列來實現的,這兩個列,一個保存的行的創建時間,一個保存行的過期時間,當然存儲的并不是實際的時間值,而是系統版本號(system version number),每開始一個新的事務,系統版本號就會遞增,事務開始時刻的系統本號會作為事務的版本號,用來和查詢到的每行記錄的版本號進行記錄,下面看一個在REPEATABLE READ隔離級別下,MVCC是如何操作的
    • SELECT
      • innodb會根據以下兩個條件檢查每行記錄,只有符合下面兩個條件的記錄,才能返回作為查詢結果
        1. innodb值只查找系統早已當前事務版本的數據行(也就是行的系統版本號小于或等于事務的系統版本號),這樣可以確保事務讀取的行,要么是在事務開始前就已經存在的,要不是事務自身插入或者修改過的
        2. 行的刪除版本要不未定義,要不大于當前事務版本號,這可以確保事務讀取到的行,在事務開始之前未被刪除
    • INSERT
      • innodb為新插入的每一行保存當前系統版本號作為行版本號
    • DELETE
      • innodb為刪除的每一行保存當前系統版本號作為行刪除標識
    • UPDATE
      • innodb為插入一條新紀錄,保存當前系統版本號作為行版本號,同時保存當前系統的版本號到原先的行作為刪除標識
  6. 保留著兩個額外系統版本號,使得大多數讀操作讀不需要加鎖。這樣設計使得讀數據操作很簡單,性能很好,并且也能保證只會讀取到符合標準的行,不足之處是每行記錄都需要額外的存儲空間,需要做更多的行檢查工作,以及一些額外的維護工作
  7. MVCC只在REPEATABLE READ和READ COMMIT兩個隔離級別下工作,其他兩個隔離級別都和MVCC不兼容,因為READ UNCOMMIT總是讀取最新的數據行,而不是符合當前事務版本的數據行,而SERIALIZEABLE則會對所有讀取的行都加鎖
  8. 下面我們就開始案例:
    *MVCC詳細講解
    • 我們執行step7的時候發現一個問題,怎么id=4的查不出來呢,按照上面的規則,id=3的事務ID是2,T3的事務ID是3,這種情況id=4是可以查出來的呢,所以說上面的規則肯定還說的不是很詳細,有遺落的地方,我們接著往下面看
  9. 我們在事務隔離中可以知道,innodb在執行select的時候會創建一個快照
    • 隔離級別大于等于可重復讀:事務塊的所有的SELECT操作都要使用同一個快照,此快照是在第一個SELECT操作時建立的
    • 隔離級別小于等于已提交讀:事務塊內的所有的SELECT操作分別創建屬于自己的快照,因此每次讀都不同,后面的SELECT操作的讀就可以讀到本次讀之前已經提交的數據
    • 當前數據可以看到哪些數據就是由這個快照決定的,快照有下面幾個屬性,并且可見性也根據這幾個屬性來判斷的
      • m_up_limit_id   一個快照,有左右邊界,左邊界是最小值,右邊界是最大值,此變量是左邊界
      • m_low_limit_id   右邊界
      • m_createor_trx_id   正在創建事務的事務ID
      • trx_ids 快照創建時,處于活動即尚未完成的讀寫事務的集合
    • 舉一個列子:新建一個快照,假設當前事務的事務ID為6,這時候讀寫事務鏈上(這個是全局的)活動的事務有{3,5,6,10},不包括只讀事務,那么調用方法創建快照時就會把{3,5,10}存儲到當前的視圖中的trx_ids(6因為是當前事務的ID,不記錄到視圖中),m_up_limit_id的值是3,m_low_limit__id是10,m_createor_trx_id是6
      • trx_id<m_up_limit_id 可見  意味著是快照之前發生的事務
      • trx_id>m_low_limit_id 不可見,意味著是快照之后發生的事務
      • trx_ids對應的事務左右的修改還處于活動狀態即還沒有提交對當前事務來說不可見
      • trx_id=m_createor_trx_id 可見
      • 公式:通過比較事務ID的值是否在[m_up_limit_id,m_low_limit_id]區間的左側,中間,還是右側判斷是否可見
        • 左側   可見
        • 中間
          • 在trx_ids中不可見
          • 等于m_createor_trx_id 可見
        • 右側  不可見
  10. innodb的MVCC技術中的多版本是根據UNDO日志來實現了,我們在上面說過,DATA_ROLL_PTR ,表示舊版本的數據位于回滾段中的位置。DB_ROLL_PTR的結構如下
    • MVCC詳細講解
  11. 多版本生成
    • 對于一個邏輯上的多版本生成過程,其方式如下
      • 最老的版本,一定是插入操作暫存到UNDO日志的版本(對于聚集索引,不是記錄的所有字段讀暫存到回滾段,而是主鍵信息被暫存)
      • 更新操作,把舊值存入UNDO日志。同一個日志反復被更新,則每次讀存入一個舊值(前像)到UNDO日志內,如此就會有多個版本,版本之間,使用DATA_POLL_PTR執行根據的版本,由此所有版本構成一個鏈表,鏈頭是索引上的記錄,鏈尾是首次插入時生成的UNDO信息。
      • 刪除操作,在UNDO日志中保存刪除標志
  12. 多版本查找
    • 對于聚集索引,可以根據DATA_ROLL_PTR就可以從回滾段中找出前一個版本的記錄,并知道此記錄是更新操作還是插入操作生成的,如果是插入操作生成的,則意味著此版本是最原始的版本,即使不可見也沒有必要在繼續回溯查找舊版本了
    • 但是查找的過程與隔離級別緊密相關
      • 如果是未提交讀隔離級別,根本不去找舊版本,在索引上讀到的記錄就被直接使用
      • 如果不是未提交隔離級別,則需要進入UNDO回滾段中根據DATA_POLL_PTR進行查找,還要判斷是否可見,如果可見,則返回,如果不可見,則一直根據DATA_POLL_PTR進行查找
    1. 有了前面的補充,我們看下是否能解釋前面step7出現的問題

      • MVCC詳細講解
      • MVCC詳細講解
      • 我們在T2的step8修改了id=1的title,但step 9,step10沒有看到,step9沒看到,大家不會有什么意外,因為step9對應的事務ID小于step8的事務ID,但step10的事務ID是大于step8的事務ID的,那么我們來分析一下是什么造成的,我們這里不說undo log的格式,我們只需要知道根據undo log我們可以知道記錄的多個版本
      • 一開始,id=1的記錄是這樣的
      • MVCC詳細講解
      • T1的step4
        • m_up_limit_id=1,m_low_limit_id=1,m_createor_trx_id=1,trx_ids={},DATA_TRX_ID=0
        • DATA_TRX_ID<m_up_limit_id, 在[m_up_limit_id,m_low_limit_id]的左側,記錄可見
      • T2的step 5
        • m_up_limit_id=1,m_low_limit_id=2,m_createor_trx_id=2,trx_ids={1},DATA_TRX_ID=0
        • DATA_TRX_ID<m_up_limit_id, 在[m_up_limit_id,m_low_limit_id]的左側,記錄可見
      • T3的step 6
        • m_up_limit_id=1,m_low_limit_id=3,m_createor_trx_id=3,trx_ids={1,2},DATA_TRX_ID=0
        • DATA_TRX_ID<m_up_limit_id, 在[m_up_limit_id,m_low_limit_id]的左側,記錄可見
      • step7修改了數據,這時候id=1的記錄是這樣的
        • MVCC詳細講解
      • T2的step8
        *m_up_limit_id=1,m_low_limit_id=2,m_createor_trx_id=2,trx_ids={1},DATA_TRX_ID=2
        • DATA_TRX_ID在[m_up_limit_id,m_low_limit_id]的中間位置,m_createor_trx_id=DATE_TRX_ID,因此可見。所以看到了title=‘商品1 push’的這一行
      • T1的step9
        • m_up_limit_id=1,m_low_limit_id=1,m_createor_trx_id=1,trx_ids={},DATA_TRX_ID=2
        • DATA_TRX_ID在[m_up_limit_id,m_low_limit_id]的右側,記錄不可見
        • 那么接著通過DATE_ROLL_PTR,去undo找到了trx_id=0的這一行
        • DATA_TRX_ID=0,DATA_TRX_ID<m_up_limit_id, 在[m_up_limit_id,m_low_limit_id]的左側,記錄可見
      • step10
        • m_up_limit_id=1,m_low_limit_id=3,m_createor_trx_id=3,trx_ids={1,2},DATA_TRX_ID=2
        • DATA_TRX_ID在[m_up_limit_id,m_low_limit_id]的中間位置,并且在trx_ids中,記錄不可見
        • 接著通過DATE_ROLL_PTR,去undo找到了trx_id=0的這一行
        • DATA_TRX_ID=0, DATA_TRX_ID=0,DATA_TRX_ID<m_up_limit_id, 在[m_up_limit_id,m_low_limit_id]的左側,記錄可見

      關于MVCC詳細講解就分享到這里了,希望以上內容可以對大家有一定的參考價值,可以學以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

临洮县| 岳普湖县| 涪陵区| 屯门区| 临夏市| 保山市| 诏安县| 四川省| 济宁市| 苍溪县| 霍邱县| 栾城县| 嘉峪关市| 宁乡县| 迁安市| 林西县| 海口市| 中超| 旌德县| 南召县| 寻甸| 长海县| 如皋市| 阳朔县| 邻水| 云林县| 石景山区| 济源市| 定远县| 焦作市| 福清市| 南平市| 郎溪县| 岳普湖县| 咸阳市| 泌阳县| 普兰店市| 樟树市| 湾仔区| 乌兰察布市| 江山市|