資料庫事務隔離級別

2021-08-05 22:39:35 字數 3440 閱讀 7475

定義: 在

資料庫操作中,為了有效保證併發讀取資料的正確性,提出的事務隔離級別。

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted(未授權讀取、讀未提交)、read committed(授權讀取、讀提交)、repeatable read(可重複讀取)、serializable(序列化),這四個級別可以逐個解決髒讀、不可重複讀、幻讀這幾類問題。*髒讀

乙個事務讀取到了另乙個事務未提交的資料操作結果。

* 不可重複讀

(non-repeatable reads):乙個事務對同一行資料重複讀取兩次,但是卻得到了不同的結果。

包括以下情況:

(1)虛讀

:事務t1讀取某一資料後,事務t2對其做了修改,當事務t1再次讀該資料時得到與前一次不同的值。

(2)幻讀

(phantom reads):事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的資料或者缺少了第一次查詢中出現的資料(這裡並不要求兩次查詢的sql語句相同)。這是因為在兩次查詢過程中有另外乙個事務插入資料造成的。

√: 可能出現    ×: 不會出現

髒讀不可重複讀

幻讀read uncommitted√√

√read committed×√

√repeatable read××

√serializable××

×注意:我們討論隔離級別的場景,主要是在多個事務併發的情況下,因此,接下來的講解都圍繞事務併發。

(1).隔離級別與併發效能的關係:

(2).設定隔離級別的原則:

•隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。

•對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為read committed,它能夠避免髒讀,而且具有較好的併發效能。儘管它會導致不可重複讀、虛讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用悲觀鎖樂觀鎖來控制。

(3)在mysql.exe程式中中設定隔離級別:

•每啟動乙個mysql.exe程式,就會獲得乙個單獨的資料庫連線。每個資料庫連線都有個全域性變數@@tx_isolation,表示當前的事務隔離級別。mysql預設的隔離級別為repeatable read。如果要察看當前的隔離級別,可使用如下sql命令:

–mysql> select @@tx_isolation;

•如果要把當前mysql.exe程式的隔離級別改為read committed,可使用如下sql命令:

–mysql> set transaction isolation level read committed;

read uncommitted 讀未提交

公司發工資了,領導把5000元打到singo的賬號上,但是該事務並未提交,而singo正好去檢視賬戶,發現工資已經到賬,是5000元整,非常高興。可是不幸的是,領導發現發給singo的工資金額不對,是2000元,於是迅速回滾了事務,修改金額後,將事務提交,最後singo實際的工資只有2000元,singo空歡喜一場。

出現上述情況,即我們所說的

髒讀,兩個併發的事務,「事務a:領導給singo發工資」、「事務b:singo查詢工資賬戶」,事務b讀取了事務a尚未提交的資料。避免了更新丟失,卻可能出現髒讀。也就是說說事務b讀取到了事務a未提交的資料。

當隔離級別設定為read uncommitted時,就可能出現髒讀,如何避免髒讀,請看下乙個隔離級別。

read committed 讀提交

singo拿著工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把singo工資卡的2000元轉到另一賬戶,並在singo之前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,為何......

出現上述情況,即我們所說的

不可重複讀

,兩個併發的事務,「事務a:singo消費」、「事務b:singo的老婆網上轉賬」,事務a事先讀取了資料,事務b緊接了更新了資料,並提交了事務,而事務a再次讀取該資料時,資料已經發生了改變。

當隔離級別設定為read committed時,避免了髒讀,但是可能會造成不可重複讀。事務a事先讀取了資料,事務b事務緊接著更新資料,並提交了事務,而事務a再次讀取該資料時,資料已經發生了改變。

大多數資料庫預設級別就是read committed,比如sql server , 

oracle

。如何解決不可重複讀這一問題,請看下乙個隔離級別。

repeatable read 重複讀

當隔離級別設定為repeatable read時,可以避免不可重複讀。當singo拿著工資卡去消費時,一旦系統開始讀取工資卡資訊(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉賬。

雖然repeatable read避免了不可重複讀與髒讀,但還有可能出現幻讀。這可以通過「共享讀鎖」與「排他寫鎖」 實現。

singo的老婆工作在銀行部門,她時常通過銀行內部系統檢視singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)為80元,而singo此時正好在外面胡吃海塞後在收銀台買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨後singo的老婆將singo當月信用卡消費的明細列印到a4紙上,卻發現消費總額為1080元,singo的老婆很詫異,以為出現了幻覺,幻讀就這樣產生了。

注:mysql的預設隔離級別就是repeatable read。

serializable 序列化

serializable是最高的事務隔離級別,同時代價也花費最高,效能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免髒讀、 不可重複讀,還避免了幻像讀。

隔離級別越高,越能保證資料的完整性與一致性,但是對併發效能的影響也越大。對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為read committed。它能夠避免髒讀取,而且具有較好的併發效能。儘管它會導致不可重複讀,幻讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用悲歡鎖或樂觀鎖來控制。

大多數資料庫的預設級別就是read committed,比如:sql server, oracle;

mysql的預設隔離級別就是repeatable read.

資料庫事務隔離級別

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...

資料庫事務隔離級別

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...

資料庫事務隔離級別

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable 這四個級別可以逐個解決髒讀 不可重複讀 幻讀 這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted re...