MySQL 四種事務隔離級別詳解介紹(二)

參考文章:MySQL 四種事務隔離級別詳解介紹

事務特性ACID中,隔離性最爲複雜,它指的是事務與事務之間不會互相影響,一個事務的中間狀態不會被其他事務感知。事務的隔離性由低到高分爲:Read uncommitted 、Read committed 、Repeatable read 、Serializable。不同的隔離性在併發事務下會引起不同的讀現象:髒讀、不可重複讀和幻讀

一、讀現象及其區別

1、髒讀(讀取了未提交的數據)

  髒讀又稱無效數據的讀出,是指在數據庫訪問中,事務T1將某一值修改,但是這種修改還沒有提交(commit),然後事務T2讀取該值,此後T1因爲某種原因撤銷對該值的修改,這就導致了T2所讀取到的數據是無效的,這個數據就是是髒數據,依據髒數據所做的操作可能是不正確的。

  例子:程序員小王妻子給小王轉零花錢,但是不小心按錯數字了,將1K按成了7K,但是還沒最後提交,這時候小王正好查看自己的零花錢,發現這個月零花錢有7K,以爲老婆開恩,非常高興。但是小王妻子發現問題,馬上回滾差點就提交了的事務,但是小王看到是7K。他看到的是他老婆還沒提交事務時的數據。這就是髒讀。小王,瞧把你美的。

2、不可重複讀(一個事務範圍內兩個相同的查詢卻返回了不同數據)

  不可重複讀,是指在數據庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同數據。這是由於查詢時系統中其他事務修改的提交而引起的。比如事務T1讀取某一數據,事務T2讀取並修改了該數據,T1爲了對讀取值進行檢驗而再次讀取該數據,便得到了不同的結果。一種更易理解的說法是:在一個事務內,多次讀同一個數據。在這個事務還沒有結束時,另一個事務也訪問該同一數據。那麼,在第一個事務的兩次讀數據之間。由於第二個事務的修改,那麼第一個事務讀到的數據可能不一樣,這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱爲不可重複讀,即原始讀取不可重複,讀取數據不一樣。

  例子:程序員小王拿着工資卡去Happy(卡里當然只有可憐1K),當他埋單時(程序員事務開啓),收費系統事先檢測到他的卡里有1K,就在這個時候!小王的妻子發現小王去Happy,就把錢全部轉出充當家用,並提交。當收費系統準備扣款時,再檢測卡里的金額,發現已經沒錢了(第二次檢測金額當然要等待小王妻子轉出金額事務提交完)。小王就會很鬱悶,明明卡里是有錢的。小王,你還是太天真了。

3、幻讀(一個事務範圍內操作不完整的現象,它對應的是插入Insert操作,而不是Update操作)

  幻讀是事務非獨立執行時發生的一種現象,它是指B事務讀取了兩次數據,在這兩次的讀取過程中A事務添加了數據,B事務的這兩次讀取出來的集合不一樣(集合數量或者集合中的元素)。例如事務T1對一個表中所有的行的某個數據項做了從“1”修改爲“2”的操作,這時事務T2又對這個表中插入了一行數據項,而這個數據項的數值還是爲“1”並且提交給數據庫。而操作事務T1的用戶如果再查看剛剛修改的數據,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺一樣,這就是發生了幻讀。

  例子:程序員小王某一天去Happy,花了1K元,然後他的妻子去查看他今天的消費記錄(全表掃描,妻子事務開啓),看到確實是花了1K元,就在這個時候,小王又花了1萬元,即Insert了一條消費記錄,並提交。當妻子打印程序員的消費記錄清單時(妻子事務提交),發現小王花了1.1萬元,似乎出現了幻覺,這就是幻讀。小王,等着跪鍵盤吧。

髒讀 某一事務讀取了另一事務未提交的髒數據
不可重複讀 某一事務分別讀取了另一事務提交前和提交後的數據
幻讀

幻讀和不可重複讀都是讀取了另一條已經提交的事務(這點就髒讀不同),所不同的是幻讀強調的集合的增減(Insert),不可重複讀強調的是讀取數據的修改(Update)

二、隔離級別鎖實現機制

排他鎖

被加鎖的對象只能被持有鎖的事務讀取和修改,其他事務無法在該對象上加其他鎖,也不能讀取和修改該對象

共享鎖

被加鎖的對象可以被持鎖事務讀取,但是不能被修改,其他事務也可以在上面再加共享鎖

特別的,對共享鎖:如果兩個事務對同一個資源上了共享鎖,事務B想更新該數據,那麼它必須等待事務A釋放其共享鎖

三、隔離級別 

1、未提交讀(Read uncommitted)

定義 未提交讀是最低的隔離級別,在這種事務隔離級別下,一個事務可以讀到另外一個事務未提交的數據
鎖機制

採用的是一級封鎖協議

a、事務在讀數據的時候並未對數據加鎖;

b、事務在修改數據的時候只對數據增加行級共享鎖,直到事務結束才釋放。

操作邏輯 a、事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新(因爲事務1並未對數據增加任何鎖)

b、當事務2對該記錄進行更新時,事務1再次讀取該記錄,能讀到事務2對該記錄的修改版本(因爲事務2只增加了共享讀鎖,事務1可以再增加共享讀鎖讀取數據),即使該修改尚未被提交,導致“髒讀”

c、事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。(因爲事務一對數據增加了共享讀鎖,事務二不能增加排他鎖進行數據的修改)

缺點 不能避免髒讀,不可重複讀,幻讀

2、提交讀(Read committed)

定義 提交讀也可以翻譯成讀已提交,在一個事務修改數據過程中,如果事務還沒提交,其他事務不能讀該數據
鎖機制

採用的是二級封鎖協議

a、事務對當前被讀取的數據加行級共享鎖,一旦讀完該行,立即釋放該行級共享鎖(非事務結束);

b、事務在更新某數據的瞬間,必須先對其加行級排他鎖,直到事務結束才釋放。

操作邏輯

a、事務1在讀取某行記錄的整個過程中,事務2都可以對該行記錄進行讀取(因爲事務1對該行記錄增加行級共享鎖的情況下,事務2同樣可以對該數據增加共享鎖來讀數據。)。

b、事務1讀取某行的一瞬間,事務2不能修改該行數據,但是,只要事務1讀取完該行數據,事務2就可以對該行數據進行修改。當事務1再次讀取該行數據,並結束事務,與第一次讀取的不一致,導致了不可重複讀。(事務1在讀取的一瞬間會對數據增加共享鎖,任何其他事務都不能對該行數據增加排他鎖。但是事務1只要讀完該行數據,就會釋放行級共享鎖,一旦鎖釋放,事務2就可以對數據增加排他鎖並修改數據

c、事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。(事務1在更新數據的時候,會對該行數據增加排他鎖,知道事務結束纔會釋放鎖,所以,在事務1沒有提交之前,事務2都能不對數據增加共享鎖進行數據的讀取。所以,提交讀可以解決髒讀的現象

缺點 不能避免不可重複讀,幻讀

3、可重複讀(Repeatable reads)

定義 由於提交讀隔離級別會產生不可重複讀的讀現象。所以,比提交讀更高一個級別的隔離級別就可以解決不可重複讀的問題
鎖機制

a、事務在讀取某數據的瞬間,必須先對其加行級共享鎖,直到事務結束才釋放;

b、事務在更新某數據的瞬間,必須先對其加行級排他鎖,直到事務結束才釋放。

操作邏輯

a、事務1在讀取某行記錄的整個過程中,事務2都可以對該行記錄進行讀取(因爲事務1對該行記錄增加行級共享鎖的情況下,事務2同樣可以對該數據增加共享鎖來讀數據。)。

b、事務1在讀取某行記錄的整個過程中,事務2都不能修改該行數據(事務1在讀取的整個過程會對數據增加共享鎖,直到事務提交纔會釋放鎖,所以整個過程中,任何其他事務都不能對該行數據增加排他鎖。所以,可重複讀能夠解決不可重複讀的讀現象

c、事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。(事務1在更新數據的時候,會對該行數據增加排他鎖,知道事務結束纔會釋放鎖,所以,在事務2沒有提交之前,事務1都能不對數據增加共享鎖進行數據的讀取。所以,提交讀可以解決髒讀的現象

缺點 不能避免幻讀

4、可序列化(Serializable)

定義 是最高的隔離級別,前面提到的所有的隔離級別都無法解決的幻讀,在可序列化的隔離級別中可以解決
鎖機制

a、事務在讀取數據時,必須先對其加表級共享鎖 ,直到事務結束才釋放;

b、事務在更新數據時,必須先對其加表級排他鎖 ,直到事務結束才釋放。

操作邏輯

a、事務1正在讀取A表中的記錄時,則事務2也能讀取A表,但不能對A表做更新、新增、刪除,直到事務1結束。(因爲事務1對錶增加了表級共享鎖,其他事務只能增加共享鎖讀取數據,不能進行其他任何操作)

b、事務1正在更新A表中的記錄時,則事務2不能讀取A表的任意記錄,更不可能對A表做更新、新增、刪除,直到事務1結束。(事務1對錶增加了表級排他鎖,其他事務不能對錶增加共享鎖或排他鎖,也就無法進行任何操作)

備註

a、無法讀取其它事務已修改但未提交的記錄。

b、在當前事務完成之前,其它事務不能修改目前事務已讀取的記錄。

c、在當前事務完成之前,其它事務所插入的新記錄,其索引鍵值不能在當前事務的任何語句所讀取的索引鍵範圍中。

5、綜述

隔離級別 髒讀 不可重複讀 幻讀
Read uncommitted Yes Yes Yes
Read committed No Yes Yes
Repeatable reads No No Yes
Serializable No No No

  特別說明:大多數數據庫默認的事務隔離級別是Read committed,比如Sql Server , Oracle。Mysql的默認隔離級別是Repeatable read

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章