一文教你快速理解 MySQL 事務隔離級別

當數據庫上有多個事務同時執行的時候,就可能出現問題:數據庫

  • 髒讀(dirty read)
  • 不可重複讀(non-repeatable read)
  • 幻讀(phantom read)

爲了解決這些問題,就有了「隔離級別」的概念,包括:ide

  • 讀未提交的(read uncommitted)
  • 讀已提交的(read committed)
  • 可重複讀(repeatable read)
  • 串行化(serializable)

下面咱們來解決3個問題:線程

  1. 髒讀、不可重複讀、幻讀是什麼意思?
  2. 每一個隔離級別是什麼含義?
  3. 事務隔離是怎麼實現的?

事務同步問題

(1)髒讀(dirty read)

示例:3d

一文教你快速理解 MySQL 事務隔離級別

在這個例子中根本不存在 id 爲 1,而且 age 爲 21 的記錄,事務1讀到了髒數據。日誌

這就是髒讀,一個事務中讀到了另外一個事務修改但未提交的數據。code

(2)不可重複讀(non-repeatable read)

示例:blog

一文教你快速理解 MySQL 事務隔離級別

不可重複讀就是一個事務中讀取2次同一條記錄,但每次讀取的結果不一樣。事務

(3)幻讀(phantom read)

示例:同步

一文教你快速理解 MySQL 事務隔離級別

幻讀就是在一個事務中一樣的查詢條件產生取得的結果不一樣,有新紀錄產生了。it

幻讀其實就是不可重複讀的一個特殊狀況。

事務隔離級別

  • 讀未提交的(read uncommitted) 是指一個事務尚未提交時,它所作的變動可以被其餘事務看到。
  • 讀已提交的(read committed) 是指一個事務只有在提交以後,它所作的變動才能被其餘事務看到。
  • 可重複讀(repeatable read)是指一個事務中看到的數據始終是一致的。
  • 串行化(serializable)會爲記錄加鎖,出現鎖衝突時,後邊的事務必須等待前邊的事務執行完成才能繼續。

下面假設一個場景,看看不一樣隔離級別時的返回結果。

有一個表 T,有一個int型字段 c,包含一條記錄 1

一文教你快速理解 MySQL 事務隔離級別

不一樣隔離級別下的值:

  • 隔離級別爲讀未提交的

V1=2,此級別下事務2的更改能夠被事務1看到。

V2 和 V3 一樣爲 2。

  • 隔離級別爲讀已提交的

V1=1,V2=2,此級別下事務2未提交的變動事務1看不到,提交後事務1能夠看到。

V3=2。

  • 隔離級別爲可重複讀

V1=1,V2=1,此級別下事務1執行期間看到的值一致。

V3=2。

  • 隔離級別爲串行化

事務2會被鎖住,等待事務1提交。V1=1,V2=1,V3=2。

事務隔離的實現

不一樣事務能夠看到不一樣的值,這是怎麼實現的呢?

有一個重要概念 」回滾日誌」。

MySQL中,每條記錄在更新的時候都會記錄一條回滾操做記錄,經過回滾操做,能夠獲得之前某一狀態的值。

例如一個值從1依次修改到4,回滾日誌就相似以下的形式:

從1改成2 <- 從3改成2 <- 從4改成3 <- 當前值爲4

還有一個重要概念 「視圖 read-view「,事務啓動時就會建立視圖,與回滾日誌對應起來。

例如3個事務,產生了3個視圖 A B C,和回滾日誌的對應關係以下:

一文教你快速理解 MySQL 事務隔離級別

那麼事務A取得的值始終爲1,其餘事務同理。即便有一個新的線程把值從4改爲了5,也對其餘事務沒影響。

相關文章
相關標籤/搜索