標籤:
關於這四個隔離等級的介紹:
未提交讀(READ UNCOMMITTED)。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料(髒讀)。
提交讀(READ COMMITTED)。本事務讀取到的是最新的資料(其他事務提交後的)。問題是,在同一個事務裡,前後兩次相同的SELECT會讀到不同的結果(不重複讀)。
可重複讀(REPEATABLE READ)。在同一個事務裡,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象(稍後解釋)。
序列化(SERIALIZABLE)。讀操作會隱式擷取共用鎖定,可以保證不同事務間的互斥。
這四個層級逐漸增強,每個層級解決一個問題
髒讀,最容易理解。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料。
不重複讀。解決了髒讀後,會遇到,同一個事務執行過程中,另外一個事務提交了新資料,因此本事務先後兩次讀到的資料結果會不一致。
幻讀。解決了不重複讀,保證了同一個事務裡,查詢的結果都是事務開始時的狀態(一致性)。但是,如果另一個事務同時提交了新資料,本事務再更新時,就會“驚奇的”發現了這些新資料,貌似之前讀到的資料是“鬼影”一樣的幻覺。
還是通過測試結果來說明這些問題吧,以下結果基於mysql的版本是 5.1.53。
READ UNCOMMITTED
SessionA
SessionB
ps:從結果可知,在sessionA還沒有commit的時候,SessionB就已經可以讀取到update的資料,儘管沒有commit.這就會導致“髒讀".
READ-COMMITTED
ps:sessionA只有提交之後,sessionB才可以讀取update的資料,這就避免了‘髒讀‘,但是還是存在問題,那就是不可重複讀取。sessionB在同一個事務中,兩次讀取的資料不一致。
REPEATABLE READ
ps: 通過設定可重複讀隔離等級,解決了同一個事務中多次讀取資料不一致的問題,
但是還是存在問題,那就是‘幻讀‘, 舉例說明,事務A在insert之前發現表裡面沒有資料,於是就準備insert資料,與此同時,事務B insert資料到表裡面並且已經commit.
這個時候事務A繼續insert, 如果某個欄位有唯一約束,則insert的時候衝突。
SERIALIZABLE
ps:這個就解決了幻讀的問題,但是影響了並發讀寫效能,sessionA獲得了共用鎖定,sessoinB是掛起的狀態,只有sessionA commit之後,sessionB才可以update(不逾時的前提下)。
MYSQL-InnoDB交易隔離等級