數據庫:事務隔離級別

數據庫事務需要滿足ACID特性,即原子性、一致性、隔離性和持久性。對於隔離級別,SQL標準定義了四種隔離級別:Read Uncommitted、Read Committed、Repeatable Read和Serializable。隔離級別依次增強。隔離級別越高,事務請求的鎖越多或者保持鎖的時間就越長,併發性就越低。所以數據庫的默認級別一般不是在最高級別的Serializable。Oracle數據庫的默認隔離級別是Read Committed而innodb的默認級別是Repeatable Read。

Read Uncommitted

隔離級別最低,可以讀取其他事務沒有提交的數據。比如,事務A執行如下操作,update t set b = 2 where a = 1;但是不提交。事務B執行select b from t where a = 1;這個時候事務B中讀取的b為2。此時事務A回滾,b的實際值就變成了1。之前事務B中看到的數據就成了髒數據,這就是髒讀。

數據庫:事務隔離級別

髒讀例子

Read Committed

可以讀取其他事務已經提交的數據。在這種級別下,可以避免髒讀,但是不能避免不可重複讀。比如,一張表t,包含列(a, b),有一條數據(1, 1)。事務A執行:select b from t where a = 1;讀取到B為1。此時事務B執行:update t set b = 2 where a = 1;並且事務B提交。這個時候,在事務A中再次執行select b from t where a = 1;查出來的數據b卻變成了2。這就是不可重複讀。與髒讀相比,不可重複讀,讀到的數據是已經提交的數據,是真實的數據,髒讀讀到的是髒數據。

數據庫:事務隔離級別

不可重複讀例子

Repeatable Read

可重複讀,可以避免不可重複讀,但是不能避免幻讀。什麼是幻讀呢?請看例子。一張表t,包含列(a, b),有一條數據(1, 1)。事務A執行:select count(*) from t where a > 0;此時,得到的結果是1。事務B執行insert into t (a, b) values(2, 2);事務B提交。此時事務A中再次執行select count(*) from t where a > 0;時,等到的結果變成了2。這就是幻讀。與不可重複讀相比,幻讀是針對範圍的,不可重複讀是針對單條記錄的。

數據庫:事務隔離級別

幻讀例子

Serializable

是最高的事務隔離級別,同時代價也花費最高,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免髒讀、不可重複讀,還避免了幻讀。

對於innodb而言,默認是Repeatable Read,但是由於其採用的next key鎖,所以在這個級別下也能避免幻讀。next key鎖是什麼呢?是gap鎖加單行記錄鎖。單行記錄鎖在單個行記錄上加鎖。gap鎖是區間鎖,鎖定一個範圍,但是不包含記錄本身。next key鎖就是這兩種鎖的結合體。

各隔離級別整體情況如下:

數據庫:事務隔離級別

各隔離級別情況


分享到:


相關文章: