隔離級別的實現原理


排他鎖(Exclusive Lock)

排他鎖(Exclusive Lock) ,   簡稱X鎖。

若事務T對數據對象A加上X鎖,則只允許T讀取和修改A,其他任何事務都不能再對A加任何類型的鎖,直到T釋放A上的鎖。這就保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。

規則1一個數據之前加X鎖, 事務提交之后釋放該X鎖。 

共享鎖(Share lock) 

共享鎖(Share lock) ,簡稱S鎖, 這個鎖和之前的排他鎖X鎖有區別, 主要用於讀取數據。 

如果一個數據加了X鎖, 就沒法加S鎖,沒法再加X鎖。

如果一個數據加了S鎖, 就可以加S鎖,沒法再加X鎖。

規則1讀一個數據之前加S鎖, 讀完之后立刻釋放該S鎖。 

規則2讀一個數據之前加S鎖, 事務提交之后立刻釋放該S鎖。 

丟失修改”的問題

事務1的修改被事務2的修改覆蓋了,事務1的修改像是丟失了。

排他鎖可以解決兩個人同時修改導致的“丟失修改”的問題,事務1修改的時候不能被其他事務修改。

讀未提交(最低的事務隔離級別)-臟數據

現象:不會丟失數據,事務1還未提交的修改能被事務2讀取。可以讀到沒有提交或者回滾的內容 (臟數據)。

原理:寫數據時加上X鎖,直到事務結束, 讀的時候不加鎖。 

讀已提交-不可重復讀

現象:能避免“丟失數據”和“臟數據”,事務1能讀到其他已提交事務的修改,出現“不可重復讀”的問題。

原理:寫數據的時候加上X鎖, 直到事務結束,  讀的時候加上S鎖, 讀完數據立刻釋放。(共享鎖規則1)

可重復讀-幻讀

現象:能避免“丟失數據”和“臟數據”, “不可重復讀”三個問題,事務1能讀取到其他事務新插入讀數據,出現“幻讀”的問題。

原理:寫數據的時候加上X鎖,  直到事務結束, 讀數據的時候加S鎖, 也是直到事務結束。(共享鎖規則2)

Serializable (串行化) 

現象:能避免“丟失數據”和“臟數據”, “不可重復讀”,“幻讀”四個問題。

原理:嚴格有序執行,事務不能並發執行。 

MVCC(多版本並發控制)

“串行化”隔離級別,雖然不會出錯,但是效率實在太低了。  避免使用!!

“可重復讀”,雖然會出現幻讀,但是也能忍受。但為了實現可重復讀, 需要在事務中對讀操作加鎖,並且得持續到整個事務結束,效率也一般,可選擇使用。

隔離級別在可重復讀和讀已提交情況下,有沒有可能在在讀的時候不用加鎖,也能實現可重復讀?

MVCC實現了保證可重復讀並在讀數據的時候不需要加鎖操作!! ps:但是在寫數據的時候,MySQL還是要加鎖的,防止寫-寫沖突。讀寫不互相等待,能極大地提高數據庫的並發能力啊。

原理

給數據庫里面的每張表加兩個隱藏的字段:事務ID,回滾指針。(事務ID就表明這一行數據是哪個事務操作的,事務ID是一個遞增的數字,每次開始新事務,這個數字就會增加。)

擴展一個Read View的數據結構記錄版本數據,它有三個部分:

(1) 當前活躍的事務列表 ,即[101,102]

(2) Tmin ,就是活躍事務的最小值, 在這里 Tmin = 101 

(3) Tmax, 是系統中最大事務ID(不管事務是否提交)加上1。 在這里例子中,Tmax = 103

(注: 在可重復讀的隔離級別下,當第一個Read操作發生的時候,Read view就會建立。 在Read Committed隔離級別下,每次發出Read操作,都會建立新的Read view。)

流程變化

原始數據

事務ID  回滾指針  name  age 
100 null sf 30

開啟兩個事務

事務id101  事務id102
開始事務    標記1  
select * from users where name='sf';  開始事務
do others things

 update users set age = 35 where name='sf';  標記2

 提交事務

select * from users where name='sf';  

在標號1 的地方,數據是這樣的:  與此同時,需要建立一個叫做Read View的數據結構。

事務ID  回滾指針  name  age 
100 null sf 30

在標號為2的地方,數據是這樣的:事務2做了修改,所以事務ID修改為102,回滾指針指向上一個事務ID的數據,即事務ID100

事務ID  回滾指針  name  age 
102  上一版本的數據 sf 35

 

按照可重復讀的要求,事務1無論讀多少次總能讀到age=30的那行記錄,即使事務2修改了age,也不受影響。

那么如何用來判斷這些數據版本記錄中哪些對你來說是可見的(可讀的)。 ”

對於上面的例子,ReadView 中事務列表是[101,102], Tmin= 101, Tmax = 103,第一次讀和第二次讀是什么樣子。

當事務101第一次讀的時候,只有一條記錄, tid = 100 ,小於Tmin,所以是可以讀的。 然后事務102做了修改。

當事務101第二次讀的時候,tid=102,程序走到了‘tid是否在Read View中這一分支,由於102確實在Read View的活動事務列表中,那就順着回滾指針找到下一行記錄,即tid為100那一行,再次判斷,這就和第一次讀一樣了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM