資料庫複習8——並發,資料庫複習8
資料庫複習CH15 並發15.1 並發的問題
由事務ACID性質的I(Isolation,獨立性),並發的事務間是透明的,穿插執行的事務會產生多種資料不一致問題(區別於資料庫不一致狀態):
- Lost Update problem:事務TA更新一個資料X後,事務TB又更新資料X,導致TA對X的更新被衝掉,即TA中“看見”的X和資料庫中的X不一致
- Uncommitted Dependency problem:TB更新了資料X後TA讀取X/更新X,但TB由於某種失敗rollback,導致TA中“看見”的X和資料庫中的X不一致
- Inconsistent Analysis problem:TA是一個先於TB開始的事務(商務邏輯上的先於),但由於並發,先執行的TA中讀取了X後,後執行的TB修改X或修改了TA開始執行時刻對於TA本來一致的但TA還未讀取並即將讀取的資料Y,導致TA“看見”的資料X、Y和其執行時的X、Y不一致
註:事務並髮帶來的問題還有很多,上面只是原書作者的一種歸類方法
15.2 並發調度和序列化(1)定義
並發調度就是安排並發的事務的所有指令執行先後順序,並保持事務內部指令順序的操作;最常見的調度是串列調度,即多個事務仍然按照串列的順序一個接一個的執行全部指令,但顯然串列調度並發度極差
不是所有調度都能保證資料庫的一致性,但是我們總期待找到一個等價於串列調度的並行調度方案(即不破壞資料庫一致性的並行調度);一般稱這樣的調度是可序列化(Serializable)的
在考慮事務的序列化時作以下幾點假設:
- 每個事務是保持資料庫一致性的,即沒有邏輯錯誤
- 串列地執行一系列事務也是保持資料庫一致性的
- 為了簡化,只考慮讀寫操作,讀寫之間可能會包含各種各樣的計算
定義事務間的兩條指令oi、oj存在衝突(Conflict)若且唯若oi、oj訪問同一資料項目X並至少有一條指令試圖write(X)
;定義兩調度S1、S2是衝突等價的,若且唯若S1可以通過交換一系列非衝突指令得到S2;顯然一個可序列化衝突等價於串列調度
(2)可串列性檢測
一般通過構造事務先序圖(事務間的有向圖)來檢測調度的可串列性;考慮並發事務集合T1,…,Tn,若Ti到Tj有弧,則Ti和Tj之間存在衝突指令Oi和Oj,並且在調度方案中Ti的衝突指令Oi靠前
構造好先序圖後根據如下定理判斷調度的可串列性:
一個調度是可串列的若且唯若它構造的先序圖無環,若先序圖無環可以通過拓撲排序構造無衝突的調度
(3)評價
可串列性檢測是事後發生的,並不適用於即時的並發控制!學習可串列性是為了更好地理解下面的並發協議
15.3 基於鎖的並發協議
鎖機制我們並不陌生,作業系統中處理進程、線程同步時很詳細地討論過
Lock(X)
並發中最簡單的鎖是二值鎖(也叫互斥鎖),一個事務Lock(X)
只有等其Unlock(X)
其他事務才能訪問;由於互斥鎖中只允許一個事務對同一資料訪問,因此不允許並發的讀操作,較為低效
更常用的高效的鎖是共用/獨佔鎖定(Shared/Exclusive Lock、S-X Lock)
(1)共用/獨佔鎖定
S-X鎖有共用和排他兩種狀態:
- 通過
Lock-S
指令擷取共用鎖定,只能對擷取了共用鎖定的資料讀取操作
- 通過
Lock-X
指令擷取獨佔鎖定,可以對擷取了獨佔鎖定的資料讀寫操作
對S-X鎖的申請由並發控制管理器管理,一個事務必須擷取了某種鎖才能繼續對某資料操作
S-X鎖協議如下:
- 事務在retrieve元組t之前必須獲得t上的S鎖
- 事務在upate元組t之前必須獲得t上的X鎖,若已有S鎖則需升級到X鎖
- 如果事務A在元組t上有X鎖,則某其他事務B對t的任何一種鎖的申請都將被拒絕
- 如果事務A在元組t上有S鎖,則某其他事務B對t的X鎖的申請將被拒絕,而對t的S鎖的申請將被允許
- 如果對某個鎖的申請一直沒有被允許,事務將一直等待,直到其他事務釋放它申請的鎖
- 通常commit和rollback時預設為釋放該事務申請的所有鎖
仔細思考上述對S-X鎖的描述,很容易發現會出現饑餓甚至是死結(死結的事務將強行釋放掉它們擁有的鎖並復原)
(2)兩階段鎖協議
兩階段鎖(Two Phase Lock)協議是一個能夠保證衝突可序列化調度方案的協議,兩階段鎖協議中事務劃分成兩個階段(兩階段之間的時間點稱作Lock Point):
兩階段鎖不能避免死結,除非加上限制條件[事務擷取的所有X鎖必須在事務結束時才被釋放],此時稱為嚴格的兩階段鎖協議
(3)自動擷取鎖
一般的資料庫語言中並不直接提供顯式鎖語句,而是將鎖協議嵌入到**原子的**read和write中,如下是一種實現方式:
READ(Ti, D) { if Ti has no lock on D { wait until no other T has a X-lock on D; grant Ti a S-lock on D; } read(D);}WRITE(Ti, D) { if Ti has no X-lock on D { wait until no other T has any lock on D; if Ti has a S-lock on D { upgrade S-lock to X-lock; } else { grant Ti a X-lock on D; } } write(D);}
(4)鎖機制的實現
一般鎖的實現由DBMS的lock manager完成,事務向lock manager發送上鎖和釋放鎖的請求,lock manager向事務發送批准(grant)申請、拒絕申請以及強制會滾的訊息(防止死結)
lock manager在名為lock table的雜湊表記錄鎖管理相關的資訊,以元組做索引,其中記錄批准鎖的事務列表(包括批准了什麼類型鎖)以及等待
15.5 鎖粒度(1)鎖的粒度
資料庫中資料的粒度從高層到底層分別是:資料庫、地區(不知道這是什麼)、檔案以及元組紀錄,可以針對不同粒度的資料上鎖
粒度較細是指對粒度層級較低的資料上鎖,這樣可以擷取更高並發度,但鎖管理開銷負載較大;粒度較粗是指對粒度層級較高的資料上鎖,這樣可以擷取低開銷的鎖管理,但並發度較低
(2)S-X鎖的粒度擴充——意圖鎖定
意圖鎖定(Intention Lock)的提出是基於一個運用粒度適中的鎖機制的資料庫系統,假設事務T申請某個關係變數R(即某表)上的X鎖,若全域掃描R中所有元組是否被其他事務鎖住,這樣開銷很大
因此為了檢測這樣粒度劃分後的鎖的衝突,必須完善X-S鎖協議,下列意圖鎖定協議應運而生:
- IS意圖共用鎖:T對某個粒度的資料對象加IS鎖,表明T意欲對該對象的後繼節點(粒度層級更低的資料對象)設定S鎖,如T想要對R的元組t設定S鎖,則先要對關係變數R加IS鎖(或對R所在的資料庫加IS鎖)
- IX意向獨佔鎖定:T對某個粒度的資料對象加IX鎖,表明T意欲對該對象的後繼節點(粒度層級更低的資料對象)設定X鎖
- SIX共用意向獨佔鎖定:T對某個粒度的資料對象加SIX鎖,相當於先加S鎖再加IX鎖,例如需要讀關係變數R的所有元組並修改某些元組,則申請SIX鎖
基於意圖鎖定的多粒度擴充協議的基本原則就是:T要對某個資料對象上鎖,則需要對它上層節點上鎖,並且申請鎖時自上而下、釋放鎖時自下而上
15.5 死結處理
DBMS的事務並發管理器處理死結有兩種機制:死結預防和死結檢測
(1)死結預防
死結預防顧名思義就是保證資料庫絕對不會進入死結狀態,一些策略如下:
- 要求所有事務在開始執行操作前擷取所有需要的鎖,叫做預先申請
- 事務對資料的上鎖順序取決於[偏序],類似於死結檢測中的等待圖
- 設定事務等待鎖的時間上限,逾時則會滾事務,稱之為逾時策略
(2)死結檢測
死結檢測是去檢測等待圖(Wait-For Graph,一種描述事務鎖依賴的有向圖)是否成環的機制,當檢測到死結時選取部分鎖會滾或者直接所有事務會滾
等待圖中有:
- 頂點V代表所有活躍的事務
- 有向邊E=Ti->Tj表示Ti正在等待Tj釋放某個元組t上的鎖,並有Tj釋放鎖後Ti申請到時,刪除邊E
可以用有向圖成環檢測的演算法來檢測是否存在死結
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。