當數據庫上有多個事務同時執行的時候,就可能出現問題:數據庫
爲了解決這些問題,就有了「隔離級別」的概念,包括:ide
下面咱們來解決3個問題:線程
示例:3d
在這個例子中根本不存在 id 爲 1,而且 age 爲 21 的記錄,事務1讀到了髒數據。日誌
這就是髒讀,一個事務中讀到了另外一個事務修改但未提交的數據。code
示例:blog
不可重複讀就是一個事務中讀取2次同一條記錄,但每次讀取的結果不一樣。事務
示例:同步
幻讀就是在一個事務中一樣的查詢條件產生取得的結果不一樣,有新紀錄產生了。it
幻讀其實就是不可重複讀的一個特殊狀況。
下面假設一個場景,看看不一樣隔離級別時的返回結果。
有一個表 T
,有一個int型字段 c
,包含一條記錄 1
。
不一樣隔離級別下的值:
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,和回滾日誌的對應關係以下:
那麼事務A取得的值始終爲1,其餘事務同理。即便有一個新的線程把值從4改爲了5,也對其餘事務沒影響。