一文詳解髒讀、不可重複讀、幻讀

雨點的名字發表於2021-11-17

前言

在MySQL的眾多儲存引擎中,只有InnoDB支援事務,所有這裡說的事務隔離級別指的是InnoDB下的事務隔離級別。

MySQL 是支援多事務併發執行的。否則來一個事務處理一個請求,處理一個人請求的時候,其它事務都等著,那估計都沒人敢用MySQL作為資料庫,因為使用者體驗太差,估計都要砸鍵盤了。

既然事務可以併發操作,這裡就有一些問題:一個事務在寫資料的時候,另一個事務要讀這行資料,該怎麼處理?一個事務在寫資料,另一個資料也要寫這行資料,又該怎麼處理這個衝突?

這就是併發事務所產生的一些問題。具體來說就是:髒讀不可重複讀幻讀


一、概念說明

以下幾個概念是事務隔離級別要實際解決的問題,所以需要搞清楚都是什麼意思。

1、髒讀

髒讀指的是讀到了其他事務未提交的資料,未提交意味著這些資料可能會回滾,也就是可能最終不會存到資料庫中,也就是不存在的資料。讀到了並一定最終存在的資料,這就是髒讀。

一文詳解髒讀、不可重複讀、幻讀

髒讀最大的問題就是可能會讀到不存在的資料。比如在上圖中,事務B的更新資料被事務A讀取,但是事務B回滾了,更新資料全部還原,也就是說事務A剛剛讀到的資料並沒有存在於資料庫中。

從巨集觀來看,就是事務A讀出了一條不存在的資料,這個問題是很嚴重的。

2、不可重複讀

不可重複讀指的是在一個事務內,最開始讀到的資料和事務結束前的任意時刻讀到的同一批資料出現不一致的情況。

一文詳解髒讀、不可重複讀、幻讀

事務 A 多次讀取同一資料,但事務 B 在事務A多次讀取的過程中,對資料作了更新並提交,導致事務A多次讀取同一資料時,結果 不一致。

3、幻讀

髒讀、不可重複讀上面的圖文都很好的理解,對於幻讀網上有很多文章都是這麼解釋的

幻讀錯誤的理解

說幻讀是 事務A 執行兩次 select 操作得到不同的資料集,即 select 1 得到 10 條記錄,select 2 得到 15 條記錄。
這其實並不是幻讀,既然第一次和第二次讀取的不一致,那不還是不可重複讀嗎,所以這是不可重複讀的一種。

正確的理解應該是

幻讀,並不是說兩次讀取獲取的結果集不同,幻讀側重的方面是某一次的 select 操作得到的結果所表徵的資料狀態無法支撐後續的業務操作。
更為具體一些:select 某記錄是否存在,不存在,準備插入此記錄,但執行 insert 時發現此記錄已存在,無法插入,此時就發生了幻讀。

舉例

假設有張使用者表,這張表的 id 是主鍵。表中一開始有4條資料。

一文詳解髒讀、不可重複讀、幻讀

我們再來看下出現 幻讀 的場景

一文詳解髒讀、不可重複讀、幻讀

這裡是在RR級別下研究(可重複讀),因為 RU / RC 下還會存在髒讀、不可重複讀,故我們就以 RR 級別來研究 幻讀,排除其他干擾。

1、事務A,查詢是否存在 id=5 的記錄,沒有則插入,這是我們期望的正常業務邏輯。

2、這個時候 事務B 新增的一條 id=5 的記錄,並提交事務。

3、事務A,再去查詢 id=5 的時候,發現還是沒有記錄(因為這裡是在RR級別下研究(可重複讀),所以讀到依然沒有資料)

4、事務A,插入一條 id=5 的資料。

最終 事務A 提交事務,發現報錯了。這就很奇怪,查的時候明明沒有這條記錄,但插入的時候 卻告訴我 主鍵衝突,這就好像幻覺一樣。這才是所有的幻讀。

不可重複讀側重表達 讀-讀,幻讀則是說 讀-寫,用寫來證實讀的是鬼影


二、事務的隔離級別

上述所說的"髒讀","不可重複讀","幻讀"這些問題,其實就是資料庫讀一致性問題,必須由資料庫提供的事務隔離機制來進行解決。

一文詳解髒讀、不可重複讀、幻讀

首先說讀未提交,它是效能最好,也可以說它是最野蠻的方式,因為它壓根兒就不加鎖,所以根本談不上什麼隔離效果,可以理解為沒有隔離。

再來說序列化。序列化就相當於上面所說的,處理一個人請求的時候,別的人都等著。讀的時候加共享鎖,也就是其他事務可以併發讀,但是不能寫。寫的時候加排它鎖,其他事務不能併發寫也不能併發讀。

最後說讀提交和可重複讀。這兩種隔離級別是比較複雜的,既要允許一定的併發,又想要兼顧的解決問題。MySQL預設事務隔離級別為可重複讀(RR),oracle預設事務隔離級別為讀已提交(RC),

資料庫的事務隔離越嚴格,併發副作用越小,但付出的代價越大;因為事務隔離本質就是使事務在一定程度上處於序列狀態,這本身就是和併發相矛盾的。

同時,不同的應用對讀一致性和事務隔離級別是不一樣的,比如許多應用對資料的一致性沒那麼個高要求,相反,對併發有一定要求。

這篇文章起了個開頭,接下來會寫文章來回答下面的問題

1、MySQL 是如何實現這幾個隔離級別的呢?它們底層的工作原理是什麼呢?

2、雖然MySQL預設事務隔離級別為可重複讀(RR),但它如何做到做到解決部分幻讀的問題?

相關文章