天天看點

MySQL的4種隔離級别?出現問題

事務隔離級别 髒讀 不可重複讀 幻讀
讀未送出(read-uncommited)
讀已送出(read-commited) ×
可重複讀(repeatable-read) × ×
可串行化(serializable) × × ×

SQL标準定義了4類隔離級别,包括了一些具體規則,用來限定事務内外的哪些改變是可見的,哪些是不可見的。低級别的隔離一般支援更高的并發處理,并擁有更低的系統開銷。

Read Uncommitted

在該隔離級别,所有事務都可以看到其他未送出事務的執行結果。本隔離級别很少用于實際應用,因為它的性能也不比其他級别好多少。

Read Committed

這是大多數資料庫系統的預設隔離級别(但不是MySQL預設的)。它滿足了隔離的簡單定義:一個事務隻能看見已經送出事務所做的改變。

Repeatable Read

這是MySQL的預設事務隔離級别,它確定同一事務的多個執行個體在并發讀取資料時,會看到同樣的資料行。InnoDB存儲引擎通過多版本并發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

MVCC是一種多版本并發控制機制,是MySQL的InnoDB存儲引擎實作隔離級别的一種具體方式,用于實作送出讀和可重複讀這兩種隔離級别。MVCC是通過儲存資料在某個時間點的快照來實作該機制,其在每行記錄後面儲存兩個隐藏的列,分别儲存這個行的建立版本号和删除版本号。

Serializable

這是最高的隔離級别,它通過強制事務排序,使之不可能互相沖突,進而解決幻讀問題。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級别,可能導緻大量的逾時現象和鎖競争。

出現問題

這四種隔離級别采取不同的鎖類型來實作,若讀取的是同一個資料的話,就容易發生問題。例如:

髒讀(Drity Read):某個事務已更新一份資料,另一個事務在此時讀取了同一份資料,由于某些原因,前一個RollBack了操作,則後一個事務所讀取的資料就會是不正确的。

不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中資料不一緻,這可能是兩次查詢過程中間插入了一個事務更新的原有的資料。

幻讀(Phantom Read):在一個事務的兩次查詢中資料量不一緻,例如有一個事務查詢了幾列(Row)資料,而另一個事務卻在此時插入了新的幾列資料,先前的事務在接下來的查詢中,就會發現有幾列資料是它先前所沒有的。