十分鐘搞懂MySQL四種事務隔離級別

隔離級別(ISOLATION LEVEL)

隔離性其實比想象要複雜。在SQL中定義了四種隔離的級別,每一種隔離級別都規定了一個事務中的修改,哪些是在事務內和事務間是可見的,哪些是不可見的。較低級別的隔離一般來講能承受更高的併發,系統的開銷也會更小。sql

下面簡單的介紹一下這四種事務的隔離級別,並添加一些實踐。數據庫

READ UNCOMMITTED(未提交讀)

在READ UNCOMMITTED級別,事務的修改,即便沒有提交,對其餘事務也都是可見的。事務能夠讀取未提交的數據,這也被稱爲髒讀(Dirty Read)。這個級別的隔離會致使不少問題,雖然在性能方面是最優的,可是缺少其餘級別的不少好處,因此這種隔離的級別不多在實際中應用。併發

  • CREATE TABLE性能

    CREATE TABLE `t` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `point` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    複製代碼
  • INSERT INTOui

    INSERT INTO t(point) VALUES(90);
    複製代碼
  • READ UNCOMMITTED實踐 開啓兩個MySQL SESSION,並將MySQL的默認隔離級別設置爲READ UNCOMMITTEDspa

    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    複製代碼

    READ UNCOMMITTED PNG

    READ UNCOMMITTED GIF
    以上的一段GIF圖顯示了具體的實踐過程,左邊部分是SESSION A,右邊是SESSION B從上面的實踐中咱們能夠看到,當隔離級別設置爲READ COMMITTED:

    • SESSION A第一次查詢point的值爲90
    • SESSION B更新point爲100
    • 此時SESSION B的更改並未提交
    • SESSION A第二次查詢point的值爲100

READ COMMITTED(讀已提交)

大多數數據庫系統默認的隔離級別都是READ COMMITTED(但MySQL不是),"讀已提交"簡單的定義:一個事務只能看見已經提交的事務的修改結果。換句話說,一個事務從開啓事務到提交事務以前,對其餘事務都是不可見的,所以在同一個事務中的兩次相同查詢結果可能不同。故這種隔離級別有時候也叫不可重複讀(NONREPEATABLE READ)。3d

  • READ COMMITTED 實踐 code

    READ COMMITTED PNG

    READ COMMMITED GIF
    以上的一段GIF圖顯示了"讀已提交"隔離級別下的實踐。咱們將隔離級別設置爲READ COMMITTED,從執行過程咱們能夠看到:

    • 第一次SESSION A查詢point爲90
    • SESSION B更新point爲100
    • 第二次SESSION A查詢point爲90
    • SESSION B提交事務
    • 第三次SESSION A查詢point爲100

    從實踐中咱們能夠看到當SESSION B的事務提交後,SESSION A就能讀取到SESSION B修改的數據。cdn

REPEATABLE READ(可重複讀)

"可重複讀"是MySQL的默認事務隔離級別。REPEATABLE READ解決了髒讀的問題,該級別保證了在同一次事務中屢次查詢相同的語句結果是一致的。可是"可重複讀"隔離級別沒法避免產生幻行(Phantom Row)的問題,MySQL的InnoDB引擎經過多版本併發控制(MVCC,Multiversion Concurrency Controller)解決了幻讀的問題。blog

  • REPEATABLE READ 產生幻行的實踐

    Phantom_rows
    從上面GIF圖顯示的過程咱們能夠看到,最後SESSION A查詢語句的結果只有一條id爲1的數據,可是咱們在插入id=2的數據的時候產生了報錯

    ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
    複製代碼

    從報錯中很容易就能看到是由於id=2的行已經存在了,前面讀取行數據的結果就是幻讀。

  • REPEATABLE READ 實踐

    REPEATABLE READ PNG

    REPEATABLE READ GIF
    上面的圖片顯示了在"可重複讀"隔離界別下的實踐,咱們將隔離界別設置爲REPEATABLE READ,咱們能夠看到:

    • 第一次SESSION A查詢point爲90
    • SESSION B更新point爲100
    • 第二次SESSION A查詢point爲90
    • SESSION B提交事務
    • 第三次SESSION A查詢point爲90

    咱們從實踐中能夠看到不管SESSION B怎麼改變,SESSION A在事務開啓後同一查詢語句查詢的結果都是一致的。

SERIALIZABLE(可串行化)

SERIALIZABLE是最高的隔離級別,它一般經過強制事務串行,避免了前面說的幻讀問題。簡單來講,"可串行化"會在讀取的每一行數據上都加鎖,因此可能會致使大量的鎖等待和超時問題,因此在實際的生產環境中也不多會用到這個隔離級別,只有在很是須要確保數據的一致性切能夠接受沒有併發的狀況下,纔會考慮使用這個隔離級別。

  • SERIALIZABLE實踐

    REPEATABLE READ PNG

    SERIALIZABLE GIF
    上面的GIF顯示了在"可串行化"隔離級別下的實踐。咱們將隔離級別設置爲SERVILAZABLE,從執行的過程當中咱們能夠看到:

    • 第一次SESSION A查詢結果只有id=1
    • SESSION B 插入id=2的數據,由於SESSION A的事務還未提交,此時鎖等待。
    • 第二次SESSION A查詢結果仍然是隻有一行id=1
    • SESSION A提交事務,在提交事務的瞬間SESSION A釋放鎖,SESSION B鎖等待結束
    • SESSION B提交事務
    • 第三次SEESION A查詢結果出現了id=1和id=2這兩條記錄

    從上面的過程咱們能夠看到,"可串行化"是經過對每一行數據都加鎖的方式來避免幻行問題,這種方式效率很是的低,很容易形成較長時間的鎖等待。

相關文章
相關標籤/搜索