事務-隔離級別-對標MVCC

學習思路

  1. 事務的隔離級別簡述
  2. MVCC原理
  3. 結合隔離級別對標MVCC-快照讀
  4. Next-key Lock-當前讀

一、事務的隔離級別簡述

由低到高

  1. READ UNCOMMITTED(讀未提交):一次讀取中,可以讀到其它事務未提交的數據
    1. 開啓兩個事務A、B(兩個用戶同時訪問)
    2. A事務新增/修改(insert/update)一條數據,但事務未執行完畢(未提交)
    3. B事務可以看到A事務新增/修改的數據
    4. 這就是傳說中的“髒讀”(讀到了沒有持久化的數據)
  2. READ COMMITTED(讀已提交):只能讀到其它事務已經提交的數據,未提交的讀不到

    1. 開啓兩個事務A、B(兩個用戶同時訪問)

    2. A事務新增/修改(insert/update)一條數據,但事務未執行完畢(未提交)

    3. B事務按條件查詢數據,假如查出3條

    4. A事務提交

    5. B事務按照第3步查詢條件再次查詢一遍,查出了A事務提交的數據(和3查詢的條件一樣結果不一樣)

    6. 同一事務兩次查詢的結果不一樣,這就是傳說中的不可重複讀

  3. REPEATABLE READ(可重複讀):一個事務中每次查詢的結果都一樣,insert的時候如果其它事務已經insert了,會報錯

    1. 開啓兩個事務A、B(兩個用戶同時訪問)

    2. B事務按照一定條件讀取數據

    3. A事務新增(insert)一條數據,並提交

    4. B事務再操作一遍2,發現兩次查詢結果一模一樣

    5. B事務新增一條數據(insert)提交,此時發現報錯(主鍵衝突)

    6. 我們在做insert的時候一般先select,如果沒有就insert;此時發現查詢沒查出來但保存的時候說已經有了,這就是傳說中的幻讀

    7. mysql的默認隔離級別

  4. SERIALIZABLE(串行化)

    1. 每次查詢都會串行加鎖,避免了髒讀、不可重複讀、幻讀

    2. 但需要頻繁的操作鎖佔用的資源

    3. 高併發下嚴重耗資源,可能伴有大量超時

二、MVCC原理

  1. MVCC:多版本併發控制機制
  2. 談到併發,不得不說鎖
    1. 讀鎖:又稱共享鎖;多個事務可以共同讀取數據,但不能寫,必須釋放讀鎖後才能進行讀以外的其它操作
    2. 寫鎖:又稱排它鎖;多個事務不能同時操作有寫鎖的數據,持有寫鎖的事務可對數據有讀寫權限
    3. 表鎖:鎖的粒度是整個表;當事務持有表鎖時,其它事務不能操作整張表,事務結束時方可操作
    4. 行鎖:鎖的粒度是整行;當事務持有行鎖時,其它事務不能對改行操作,鎖的粒度相對較小,高併發情況下適應性強
    5. mysql默認行鎖
    6. MVCC在我看來就是樂觀鎖的實現,避免了各種鎖的資源消耗
  3. MVCC的實現方式
    1. 在表的最後添加了兩列,create_version(創建數據的版本),delete_verion(刪除數據的版本)
  4. MVCC在實際的增刪改查中是怎麼實現的
    1. insert:新增時create_verion爲當前事務版本,delete_version爲空
    2. update:修改時實際是先將數據標記爲已刪除,然後新增一條數據;舊數據delete_version改爲當前事務版本,新數據create_time爲當前事務版本delete_version爲空
    3. delete:刪除時,刪除當前事務版本號對應的數據
    4. select:查詢時要滿足條件:create_version<=當前事務版本號<delete_version;即:已經新增的,但未被刪除的才能查出來
    5. 這裏的刪除,不是真正意義上的刪除,而是刪除標識delete_version;只有真正commit時纔是真正的刪除

三、結合隔離級別對標MVCC-快照讀

  1. READ UNCOMMITTED ,不適用MVCC讀,可以讀到其他事務修改甚至未提交的
  2. READ COMMITTED ,其他事務對數據庫的修改,只要已經提交,其修改的結果就是可見的,與這兩個事務開始的先後順序無關,不完全適用於MVCC讀,像你說的100的讀101的是可以的(按照MVCC理論應該不行的),但適用102讀101(能套MVCC理論)。
  3. REPEATABLE READ,可重複讀,完全適用MVCC,只能讀取在它開始之前已經提交的事務對數據庫的修改,在它開始以後,所有其他事務對數據庫的修改對它來說均不可見
  4. SERIALIZABLE ,完全不適合適用MVCC,這樣所有的query都會加鎖,再它之後的事務都要等待

MVCC只工作在REPEATABLE READ和READ COMMITED隔離級別下

四、Next-key Lock-當前讀

  1. Next-key Lock是行鎖和間隙鎖的結合

  2. innodb對於行的查詢(rr級別的當前讀)使用next-key lock

  3. Next-locking keying爲了解決Phantom Problem幻讀問題

  4. 當查詢的索引含有唯一屬性時,將next-key lock降級爲record key

  5. Gap鎖設計的目的是爲了阻止多個事務將記錄插入到同一範圍內,而這會導致幻讀問題的產生

  6. 有兩種方式顯式關閉gap鎖:(除了外鍵約束和唯一性檢查外,其餘情況僅使用record lock) 

    1. 將事務隔離級別設置爲RC  

    2. 將參數innodb_locks_unsafe_for_binlog設置爲1

  7. 使用條件

    1. 必須在RR級別下

    2. 檢索條件必須有索引(沒有索引的話,mysql會全表掃描,那樣會鎖定整張表所有的記錄,包括不存在的記錄,此時其他事務不能修改不能刪除不能添加)

總結:在mysql中,提供了兩種事務隔離技術,第一個是mvcc,第二個是next-key技術。這個在使用不同的語句的時候可以動態選擇。我們執行select時默認走mvcc,其它update、insert、delete時走當前讀

 

公衆號主要記錄各種源碼、面試題、微服務技術棧,幫忙關注一波,非常感謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章