mysql事務隔離級別/髒讀/不可重複讀/幻讀詳解

1、四種事務隔離級別mysql

1.1 read uncommitted 讀未提交sql

即:事務A能夠讀取到事務B已修改但未提交的數據。session

除非是文章閱讀量,每次+1這種無關痛癢的場景,通常業務系統沒有人會使用該事務隔離級別,標準實在太寬鬆了。併發

 

1.2 read committed 讀已提交(簡稱RC)分佈式

即:事務A只能讀取到事務B修改並已提交的數據。性能

這個級別相對要嚴格一些,至少是要等其它事務把變動提交到db,才能讀取到,聽上去蠻靠譜的。可是有些業務場景,好比會員系統中,若是要在一個事務中,屢次讀取用戶身份,判斷是否會員,若是剛開始讀取到該用戶是會員,作了一些邏輯處理,後面又讀到用戶不是會員了,這就有點崩潰,不知道如何繼續。這種但願同1個事務中,關鍵數據無論讀取屢次次,結果都同樣,RC級別就不行了。測試


1.3 repeatable read 可重複讀spa

即:同一個事務中,屢次讀取某一行記錄,始終是同樣的值,無論在此期間,其它事務有沒有修改過該數據(不管是否提交)。該級別解決了RC不可重複讀的問題,可是存在幻讀問題(幻讀後面會詳解)。code

 

1.4 serializable 串行化blog

即:一個事務在修改其它數據時,若是有其它事務也想改,必須等前面的事務提交或回滾後,才能繼續。最嚴格的級別,可是性能最低,也幾乎沒人用。

 

2、髒讀/不可重複讀/幻讀
2.1 髒讀

 

驗證:

a. 找一個mysql環境,建一個測試表t_people,就2列 id ,name

b. 開二個mysql終端,連到db上,爲方便講解,這2個終端稱爲「終端1」、「終端2」,終端1裏輸入:

set session transaction isolation level read uncommitted;
start transaction;

即:設置當前會話的隔離級別爲"讀未提交"。

終端2裏,輸入:

start transaction;
update t_people set name='xxx' where id=1;

而後再回到「終端1」,執行 

select id,name from t_people where id=1;

能夠看到,讀取到了未提交的髒數據 。 終端2裏,此時若是執行rollback回滾 

終端1裏,繼續執行

select id,name from t_people where id=1;

能夠發現最新結果,已是回滾後的數據。很顯然:若是有髒讀問題出現,就更加保證不了「可重複讀」。

 

2.2 不可重複讀

 

將事務隔離級別設置成read committed(即:讀已提交),可解決髒讀問題,但知足不了「可重複讀需求」。

驗證方法跟剛纔相似,終端1裏輸入:

set session transaction isolation level read committed;

將級別設置成RC,而後2個終端裏都開啓事務,終端2中,修改一行數據,可是不提交,此時終端1裏應該是讀不到終端2修改的數據。而後終端2提交,終端1才能讀到修改後的數據。終端2若是繼續修改、提交,終端1裏再讀取這1行,將是最新的值。(也就是隻說,只要終端2不斷修改,不斷提交,終端1裏就能讀到這行不一樣的新值,即:保證不了同1個事務中,同一行數據,屢次重複讀取的值不變)

 

2.3 幻讀

將隔離級別繼續調整至Repeatable Read,仍是剛纔的場景,變成這樣:

 

事務A對於同一行數據,無論讀多少次,始終是相同的值,徹底不理會有沒有其它事務在修改它。有點:「兩耳不聞窗外事,一心只讀聖賢書」的味道。可是這也有問題,好比秒殺訂單系統中,事務A第1次讀取商品庫存,發現還有1個,能夠下單,趕忙繼續,可是此時,可能有另外一個事務,也在下單,已經提交了訂單,把庫存減爲0了,事務A並不知道,由於屢次讀取庫存的值是同樣的,仍是1,最後仍然把訂單建立了,造成超賣。

驗證方法:

set session transaction isolation level repeatable read;

剩下的步驟跟前面相似,就不重複贅述了。 

 

2.4 串行化

從db層面,要想同時解決髒讀、不可重複讀、幻讀,只有串行化這個級別能夠作到。

set session transaction isolation level serializable;

以下圖:終端1設置串行化後,緊接着select xxx where id=1這條語句後,id=1的這行記錄,就被鎖了。

在終端2裏,更新其它記錄(即:id不等於1)能夠正常成功,可是更新id=1 時,就會卡住,除非終端1把事務提交或回滾,不然將一直卡着,直到超時失敗。

 

小結

隔離級別   存在的問題
讀未提交    髒讀、不可重複讀、幻讀
讀已提交   不可重複讀、幻讀
可重複讀 幻讀
串行化 性能問題

隔離級別越嚴格,db綜合性能越低。

 

建議:

大多數狀況下,RC(讀已提交)基本上就足夠了,若是併發度高,能夠考慮「RC級別+(應用層)分佈式鎖」,這樣即能保證數據正確,對db的性能壓力也較低。

相關文章
相關標籤/搜索