資料併發帶來的各種情況

2021-08-30 14:43:54 字數 2932 閱讀 8956

一、資料併發帶來的各種情況

①髒讀:事務a讀到事務b尚未提交的資料,並基於這個資料進行後續操作

②不可重複讀:事務a讀取資料後,被事務b修改或刪除,事務a再次讀取時前後兩次讀取的資料不一致

③幻像讀:事務a讀取資料後,事務b新增了資料,事務a再次讀取是前後兩次讀取的資料不一致

不可重複讀和幻想讀的區別:

幻象讀和不可重複讀是兩個容易混淆的概念,前者是指讀到了其它已經提交事務的新增資料,而後者是指讀到了已經提交事務的更改資料(更改或刪除),為了避免這兩種情況,採取的對策是不同的,防止讀取到更改資料,只需要對操作的資料新增行級鎖,阻止操作中的資料發生變化,而防止讀取到新增資料,則往往需要新增表級鎖——將整個表鎖定,防止新增資料(oracle使用多版本資料的方式實現)。

④第一類更新丟失:事務a和事務b同時訪問同乙個資料,事務b先提交修改,事務a回滾操作。導致事務b的修改丟失

⑤第二類更新丟失:事務a和事務b同時訪問同乙個資料,事務b先提交修改,事務a再提交。導致事務b的修改被覆蓋

第一類更新丟失是很嚴重的操作,如果控制不當,可能導致在乙個長時間的大型事務中,所有的操作都被回滾。所以所有的資料庫都不支援這種併發情況。

二、資料庫的鎖機制

從鎖的作用範圍來分,可以分為:行級鎖和表級鎖

從鎖的排他性來分,可以分為:共享鎖和獨佔鎖(排他鎖),

其中共享鎖允許共享,但阻止獨佔鎖。獨佔鎖不但不允許共享鎖,且不允許其它獨佔鎖

於是組合起來就有:

①行共享鎖:允許多個會話共享鎖定的行資料,但不允許對這些行的獨佔鎖。例如select ...for update

②行獨佔鎖:對行進行獨佔,不允許其它的共享鎖(表,行)、獨佔鎖(表,行)和表共享行獨佔鎖。例如insert,update

③表共享鎖:允許多個會話共享表資料,但不允許其它的獨佔鎖(表,行)、表共享行獨佔鎖。可以實現表級事務一致性

④表獨佔鎖:對錶進行獨佔,不允許其它的共享鎖(表,行)、讀佔鎖(表,行)和表共享行獨佔鎖。達到序列化操作級別

⑤表共享行獨佔鎖:允許多個會話共享表資料,但同一時刻只能有乙個行獨佔鎖。可以達到資料共享同時防止髒讀、不可重複讀、幻像讀

表共享鎖定可以讓會話具有對錶事務級一致性訪問,因為其它會話在你提交或者回溯該事務並釋放對該錶的鎖定之前不能更改這個被鎖定的表(因為要修改表的記錄,就必須獲得行獨佔鎖,但是共享鎖會阻止獨佔鎖的獲取,這樣原來其它正在讀取表記錄的事務就不會出現髒讀、不可重複讀、幻像讀的情況了); 

表共享行獨佔鎖與其不同則是多了乙個行獨佔,這樣效率更高。

三、事務隔離級別

儘管資料庫為使用者提供了鎖的dml操作方式,但直接使用鎖管理是非常麻煩的,因此資料庫為使用者提供了自動鎖機制。只要使用者指定會話的事務隔離級別,資料庫就會分析事務中的sql語句,然後自動為事務操作的資料資源新增上適合的鎖。此外資料庫還會維護這些鎖,當乙個資源上的鎖數目太多時,自動進行鎖公升級以提高系統的執行效能,而這一過程對使用者來說完全是透明的

下面是ansi iso92定義的4個事務隔離級別以及對應的對資料併發的處理

read commitited:不允許讀取未提交的資料,但可以讀取已提交的資料。所以可能出現不可重複讀、和幻像讀(讀的過程依然可以被修改、增加、刪除)

repeatable read:通過行鎖定,在讀的資料不允許其它程序修改。確保已讀取的資料不被修改、刪除(不可重複讀)但無法阻止其它程序寫入新資料,所以不能確保讀取到新的資料(幻像讀)

serializable:通過表鎖定,徹底禁止讀取期間其它程序的修改、刪除(遮蔽不可重複讀)和增加(遮蔽幻像讀)

但是不管是那種隔離級別,對第一類丟失更新都是不能接收的

解決方案:為了避免上面出現的幾種情況,在標準sql規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。 

● 未授權讀取,也稱為讀未提交(read uncommitted):允許髒讀取,但不允許更新丟失。如果乙個事務已經開始寫資料,則另外乙個資料則不允許同時進行寫操作,但允許其他事務讀此行資料。該隔離級別可以通過「排他寫鎖」實現。 

● 授權讀取,也稱為讀提交(read committed):允許不可重複讀取,但不允許髒讀取。這可以通過「瞬間共享讀鎖」和「排他寫鎖」實現。讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。 

● 可重複讀取(repeatable read):禁止不可重複讀取和髒讀取,但是有時可能出現幻影資料。這可以通過「共享讀鎖」和「排他寫鎖」實現。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。 

● 序列化(serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能乙個接著乙個地執行,但不能併發執行。如果僅僅通過「行級鎖」是無法實現事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作的事務訪問到。 

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

事務併發帶來的問題

髒讀 事務a對某個資料進行修改,但是還沒提交到資料庫中 此時事務b對這個資料進行訪問,我們把b事務訪問到的這個未提交的資料稱為 髒資料 事務b的這種行為稱為 髒讀 丟失修改 事務a和事務b同時對某乙個資料進行訪問,且此時a修改了資料如a a 1,b同時也對a進行修改,a a 1,此時a的修改結果將會...

裝飾器的各種情況。

裝飾器 第一步 基本函式 def chiji print 吃雞真得勁 呼叫函式 chiji 第二步 擴充套件功能 不能直接修改原來的函式 def zhuangshi func print 吃雞之前,左手摸雞 func print 吃雞之後,右手搖雞 def chiji print 吃雞真得勁 chi...

死鎖的各種情況總結

mutex 代表乙個全域性互斥物件 voida mutex.unlock return 複製 由於在if的執行體內直接retun,而沒有呼叫unlock,導致另乙個執行緒再呼叫a方法就出現死鎖。void sub func void data process 複製 void data process1...