事務系統的隔離級別

KunlunDB發表於2022-01-20
  • 背景


筆者最近在回顧多版本併發控制(MVCC) ,上篇章 從加鎖的角度理解了幾個異常場景(有興趣的朋友可以點選檢視 「技術討論」事物系統的幾種異常場景),由此 可以發現一個 遞進關係:在解決了上一個問題時,又發現了下一個新問題。因此才引出了,根據這幾個異常場景來定義的不同的有遞進關係的隔離級別的概念。


在對事物系統的隔離級別分析中,我們同樣可以發現: 每個隔離級別,是用來解決相對一個層次的問題。


  • 事務系統的隔離級別


1、 Read-Uncommited 讀未提交


該隔離級別解決第一個層面的異常場景:更新丟失。 該隔離級別,可以讀到任意時刻的資料,但是對未提交的其他事務正在修改的資料,無法同時寫。我們也可以理解,在這樣一個隔離級別下,對資源的所有的操作,加了讀鎖。如圖1所示:

事務系統的隔離級別

圖1

2、 Read-Commited 讀已提交


該隔離級別,解決第二個層面的異常場景:髒讀。 該隔離級別,使得未提交的資料不能被讀取。可以理解為,在該隔離級別下,對要修改的資料,讀鎖升級成了寫鎖,導致其他事務無法對該資料進行讀取,因而保證了不會出現髒讀的問題。 如圖2 所示:

事務系統的隔離級別

圖2


3、 Repeatable-Read 可重複復讀

該隔離級別,解決第三個層面的問題:不可重複讀。 該隔離級別下,一個事務對所涉及到的資料,不論是讀操作還是寫操作,一律加寫鎖,因而保證了其他的事務,既不能讀取,也不能修改這部分資料,因此確保了在事務執行過程中,這些被鎖定的資料,不會被其他的事務修改,確保不會出現不可重複讀的問題。如圖3所示:

事務系統的隔離級別

圖3

4、 Serializable 可序列化


該隔離級別下,解決第四個層面的問題:幻讀。 因為一個事務即便是對所有要讀寫的資料全部加寫鎖來實現徹底的排他,但是無法預知哪些資料是會新產生的,因此要確保不產生幻讀的情況,唯一的做法就是實現序列化事務,沒有併發,實現根本性的事務隔離,前序事務未結束,後序事務不得開始。如圖4所示:

事務系統的隔離級別

圖4

上述對事務隔離級別的描述,可以總結為以下的圖,就是一個 逐層遞進,逐層解決的過程。如圖5所示:

事務系統的隔離級別

圖5


  • 總結與思考


從上面的圖和分析中,我們考慮問題的角度都是一般性的事務系統,不涉及到具體的實現,站在事務系統的角度來說,要解決幻讀的問題,需要實現序列化的隔離級別。

但是MySQL在 rr的隔離級別,已經實現了對幻讀的避免。這是為什麼呢?為何 MySQL可以在不實現序列化的情況下,完成對幻讀問題的解決?

這裡的原因與 MySQL-innoDB 的資料組織形式密切相關: 因為 innoDB 的資料時有序存放的。

這裡的有序存放就帶來了一個潛在的事實: 相同謂詞所能夠匹配到的資料,一定時物理上存放在相鄰的位置上的。

基於這樣的事實, MySQ L通過一種新的型別的鎖 “間隙鎖”來保證無法產生幻讀,就是因為多鎖了那一部分間隙,導致新增的資料,無法寫入被鎖住的間隙,因此確保了不會出現幻讀。

END


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011764/viewspace-2853163/,如需轉載,請註明出處,否則將追究法律責任。

相關文章