資料庫事務的四種隔離級別

neuSnail發表於2017-12-21

資料庫定義了四種隔離級別:

  • Read Uncommitted(未提交讀)
  • Read Committed(提交讀)
  • Repeatable Read(重複讀)
  • Serializable(序列化)

這四種隔離依次升高,隔離級別越低,系統開銷越小,併發支援性更高。

使用命令select @@global.tx_isolation可以檢視當前資料庫使用的隔離級別

在介紹四種隔離級別前先說明三種在使用事務時會出現的特殊(大部分情況會導致錯誤)讀型別。

  • 髒讀
    髒讀是指一個事務a修改或新增了一條資料,在a事務提交之前,另一個事務b讀到了這條資料,並進行了操作。a如果回滾的話,髒讀可能會導致b操作不存在的資料。
  • 不可重複讀
    在一次事務中的兩次相同條件的查詢不一致,比如a事務執行select count(*) from user where name=`alex` 這時事務b插入了一條資料name=alex並提交這就會導致事務a第二次查詢的時候多了一個計數
  • 幻讀
    幻讀與不可重複讀相反,事務a與事務b是完全隔離的,事務a執行`select id from user得到的id為1和2.這個時候b事務在user表中新增了一條資料id=3並提交,然後事務a想新增一條id為3的資料,如果id是唯一的,那a就會發現插不進去並提示dumplicate entry 3 for key id,原因是事務a阻止事務b的插入行為。

注意不要混淆不可重複讀和幻讀

Read Uncommited

  • 在RU模式下,即使事務沒有commit,在其他事務中仍可以讀到未提交的資料。
  • RU是所有隔離級別中最低的一種。RU模式會導致髒讀

Read Commited

  • RC模式下,事務只能讀取到已經commit的資料。
  • 比如事務a在執行時,如果事務b沒有提交,a是讀不到b的資料的。如果b提交a便能讀到b修改的資料。
  • RC可以避免髒讀,但是會導致不可重複讀。
  • 大部分系統使用的是RC模式

Repeatable

  • RR模式下,事務的多次Read不會受其他事務的影響(無論提交與否)
  • 可以理解為RR模式下事務a在建立的時候獲取了一次當前時刻資料的快照,快照不受其餘事務的影響。
  • RR模式可能會導致幻讀,因為無法感知其餘事務,可能導致重複的插入。
  • mysql innoDB的RR模式可以一定程度避免幻讀,該特性是通過間隙鎖(gap lock)來實現的,間隙鎖的原理可以參照這篇文章http://www.jianshu.com/p/bf86…

Serializable

  • 序列化,顧名思義,是將所有讀寫操作完全序列。
  • 序列化是所有隔離級別中最高的
  • 每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞
  • 序列化對資源的開銷大,對併發支援不好,只在,某些場景下使用。

最後給出四個隔離級別對三種讀型別的對照表:

隔離級別 髒讀 不可重複讀 幻讀
Read Uncommited 可能 可能 可能
Read Commited 不可能 可能 可能
Repeatable Read 不可能 不可能 可能
Serializable 不可能 不可能 不可能

相關文章