久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

怎么淺析數據庫并發控制

162次閱讀
沒有評論

共計 4448 個字符,預計需要花費 12 分鐘才能閱讀完成。

怎么淺析數據庫并發控制,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

數據庫事務隔離發展標準一文中,從標準制定的角度介紹了數據庫的隔離級別,介紹了 Read Uncommitted、Read Committed、Repeatable Read、Serializable 等隔離級別的定義。下面就來看看究竟有哪些常見的實現事務隔離的機制,稱之為并發控制(Concurrency Control)。

原理

所謂并發控制,就是保證并發執行的事務在某一隔離級別上的正確執行的機制。需要指出的是并發控制由數據庫的調度器負責,事務本身并不感知,如下圖所示,Scheduler 將多個事務的讀寫請求,排列為合法的序列,使之依次執行:

這個過程中,對可能破壞數據正確性的沖突事務,調度器可能選擇下面兩種處理方式:

Delay:延遲某個事務的執行到合法的時刻

Abort:直接放棄事務的提交,并回滾該事務可能造成的影響

可以看出 Abort 比 Delay 帶來更高的成本,接下來我們就介紹不同的并發控制機制在不同情況下的處理方式。

分類

如上圖所示,這里從橫縱兩個維度,對常見的并發控制機制進行分類:

1. 樂觀程度

不同的實現機制,基于不同的對發生沖突概率的假設,悲觀方式認為只要兩個事務訪問相同的數據庫對象,就一定會發生沖突,因而應該盡早阻止;而樂觀的方式認為,沖突發生的概率不大,因此會延后處理沖突的時機。如上圖橫坐標所示,樂觀程度從左向右增高:

基于 Lock:最悲觀的實現,需要在操作開始前,甚至是事務開始前,對要訪問的數據庫對象加鎖,對沖突操作 Delay;

基于 Timestamp:樂觀的實現,每個事務在開始時獲得全局遞增的時間戳,期望按照開始時的時間戳依次執行,在操作數據庫對象時檢查沖突并選擇 Delay 或者 Abort;

基于 Validation:更樂觀的實現,僅在 Commit 前進行 Validate,對沖突的事務 Abort

可以看出,不同樂觀程度的機制本質的區別在于,檢查或預判沖突的時機,Lock 在事務開始時,Timestamp 在操作進行時,而 Validation 在最終 Commit 前。相對于悲觀的方式,樂觀機制可以獲得更高的并發度,而一旦沖突發生,Abort 事務也會比 Delay 帶來更大的開銷。

2. 單版本 VS 多版本

如上圖縱坐標所示,相同的樂觀程度下,還存在多版本的實現。所謂多版本,就是在每次需要對數據庫對象修改時,生成新的數據版本,每個對象的多個版本共存。讀請求可以直接訪問對應版本的數據,從而避免讀寫事務和只讀事務的相互阻塞。當然多版本也會帶來對不同版本的維護成本,如需要垃圾回收機制來釋放不被任何事物可見的版本。

需要指出的是這些并發控制機制并不與具體的隔離級別綁定,通過沖突判斷的不同規則,可以實現不同強度的隔離級別,下面基于 Serializable 具體介紹每種機制的實現方式。

基于 Lock

基于 Lock 實現的 Scheduler 需要在事務訪問數據前加上必要的鎖保護,為了提高并發,會根據實際訪問情況分配不同模式的鎖,常見的有讀寫鎖,更新鎖等。最簡單地,需要長期持有鎖到事務結束,為了盡可能的在保證正確性的基礎上提高并行度,數據庫中常用的加鎖方式稱為兩階段鎖(2PL),Growing 階段可以申請加鎖,Shrinking 階段只能釋放,即在第一次釋放鎖之后不能再有任何加鎖請求。需要注意的是 2PL 并不能解決死鎖的問題,因此還需要有死鎖檢測及處理的機制,通常是選擇死鎖的事務進行 Abort。

Scheduler 對沖突的判斷還需要配合 Lock Table,如下圖所示是一個可能得 Lock Table 信息示意,每一個被訪問的數據庫對象都會在 Lock Table 中有對應的表項,其中記錄了當前最高的持有鎖的模式、是否有事務在 Delay、以及持有或等待對應鎖的事務鏈表;同時對鏈表中的每個事務記錄其事務 ID,請求鎖的模式以及是否已經持有該鎖。Scheduler 會在加鎖請求到來時,通過查找 Lock Table 判斷能否加鎖或是 Delay,如果 Delay 需要插入到鏈表中。對應的當事務 Commit 或 Abort 后需要對其持有的鎖進行釋放,并按照不同的策略喚醒等待隊列中 Delay 的事務。

基于 Timestamp

基于 Timestamp 的 Scheduler 會在事務開始時候分配一個全局自增的 Timestamp,這個 Timestamp 通常由物理時間戳或系統維護的自增 id 產生,用于區分事務開始的先后。同時,每個數據庫對象需要增加一些額外的信息,這些信息會由對應的事務在訪問后更新,包括:

RT(X): 最大的讀事務的 Timestamp

WT(X): 最大的寫事務的 Timestamp

C(X): 最新修改的事務是否已經提交

基于 Timestamp 假設開始時 Timestamp 的順序就是事務執行的順序,當事務訪問數據庫對象時,通過對比事務自己的 Timestamp 和該對象的信息,可以發現與這種與開始順序不一致的情況,并作出應對:

Read Late:比自己 Timestamp 晚的事務在自己想要 Read 之前對該數據進行了寫入,并修改了 WT(X),此時會 Read 不一致的數據。

Write Late: 比自己 Timestamp 晚的事務在自己想要 Write 之前讀取了該數據,并修改了 RT(X),如果繼續寫入會導致對方讀到不一致數據。

這兩種情況都是由于實際訪問數據的順序與開始順序不同導致的,Scheduler 需要對沖突的事務進行 Abort。

Read Dirty:通過對比 C(X),可以發現是否看到的是已經 Commit 的數據,如果需要保證 Read Commit,則需要 Delay 事務到對方 Commit 之后再進行提交。

基于 Validation(OCC)

基于 Validation 的方式,有時也稱為 Optimistic Concurrency Control(OCC),大概是因為它比基于 Timestamp 的方式要更加的樂觀,將沖突檢測推遲到 Commit 前才進行。不同于 Timestamp 方式記錄每個對象的讀寫時間,Validation 的方式記錄的是每個事物的讀寫操作集合。并將事物劃分為三個階段:

Read 階段:從數據庫中讀取數據并在私有空間完成寫操作,這個時候其實并沒有實際寫入數據庫。維護當前事務的讀寫集合,RS、WS;

Validate 階段:對比當前事務與其他有時間重疊的事務的讀寫集合,判斷能否提交;

Write 階段:若 Validate 成功,進入 Write 階段,這里才真正寫入數據庫。

同時,Scheduler 會記錄每個事務的開始時間 START(T),驗證時間 VAL(T),完成寫入時間 FIN(T),基于 Validataion 的方式假設事務 Validation 的順序就是事務執行的順序,因此驗證的時候需要檢查訪問數據順序可能得不一致:

RS(T) 和 WS(U) 是否有交集,對任何事務 U,FIN(U) START(T),如果有交集,則 T 的讀可能與 U 的寫亂序;

WS(T) 和 WS({U) 是否有交集,對任何事務 U,Fin(U) VAL(T),如果有交集,則 T 的寫可能與 U 的寫亂序。

Multiversion(MVCC)

對應上述每種樂觀程度,都可以有多版本的實現方式,多版本的優勢在于,可以讓讀寫事務與只讀事務互不干擾,因而獲得更好的并行度,也正是由于這一點成為幾乎所有主流數據庫的選擇。為了實現多版本的并發控制,需要給每個事務在開始時分配一個唯一標識 TID,并對數據庫對象增加以下信息:

txd-id,創建該版本的事務 TID

begin-ts 及 end-ts 分別記錄該版本創建和過期時的事務 TID

pointer: 指向該對象其他版本的鏈表

其基本的實現思路是,每次對數據庫對象的寫操作都生成一個新的版本,用自己的 TID 標記新版本 begin-ts 及上一個版本的 end-ts,并將自己加入鏈表。讀操作對比自己的 TID 與數據版本的 begin-ts,end-ts,找到其可見最新的版本進行訪問。根據樂觀程度多版本的機制也分為三類:

1. Two-phase Locking (MV2PL)

與單版本的 2PL 方式類似,同樣需要 Lock Table 跟蹤當前的加鎖及等待信息,另外給數據庫對象增加了多版本需要的 begin-ts 和 end-ts 信息。寫操作需要對最新的版本加寫鎖,并生成新的數據版本。讀操作對找到的最新的可見版本加讀鎖訪問。

2. Timestamp Ordering (MVTO)

對比單版本的 Timestamp 方式對每個數據庫對象記錄的 Read TimeStamp(RT),Write TimeStamp(WT),Commited flag(C) 信息外增加了標識版本的 begin-ts 和 end-ts,同樣在事務開始前獲得唯一遞增的 Start TimeStamp(TS),寫事務需要對比自己的 TS 和可見最新版本的 RT 來驗證順序,寫入是創建新版本,并用自己的 TS 標記新版本的 WT,不同于單版本,這個 WT 信息永不改變。讀請求讀取自己可見的最新版本,并在訪問后修改對應版本的 RT,同樣通過判斷 C flag 信息避免 Read Uncommitted。

3. Optimistic Concurrency Control (MVOCC)

對比單版本的 Validataion(OCC)方式,同樣分為三個階段,Read 階段根據 begin-ts,end-ts 找到可見最新版本,不同的是在多版本下 Read 階段的寫操作不在私有空間完成,而是直接生成新的版本,并在其之上進行操作,由于其 commit 前 begin-ts 為 INF,所以不被其他事務課件;Validation 階段分配新的 Commit TID,并以之判斷是否可以提交;通過 Validation 的事務進入 Write 階段將 begin-ts 修改為 Commit TID。

相對于悲觀的鎖實現,樂觀的機制可以在沖突發生較少的情況下獲得更好的并發效果,然而一旦沖突,需要事務回滾帶來的開銷要遠大于悲觀實現的阻塞,因此他們各自適應于不同的場景。而多版本由于避免讀寫事務與只讀事務的互相阻塞,在大多數數據庫場景下都可以取得很好的并發效果,因此被大多數主流數據庫采用。可以看出無論是樂觀悲觀的選擇,多版本的實現,讀寫鎖,兩階段鎖等各種并發控制的機制,歸根接地都是在確定的隔離級別上盡可能的提高系統吞吐,可以說隔離級別選擇決定上限,而并發控制實現決定下限。

從樂觀悲觀的程度以及單版本多版本選擇上對可用的并發控制機制選擇進行了劃分,并介紹了各種機制大體的設計思路,而距離真正的實現還有比較大的距離,包括實現細節和配套機制。比如常用的各種類型的 MVCC 中,由于多版本的存在而帶來的一些列如垃圾回收、索引管理、版本存儲等相關問題。我們之后將以 MyRocks 為例看看并發控制在工程上的具體實現。

看完上述內容,你們掌握怎么淺析數據庫并發控制的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注丸趣 TV 行業資訊頻道,感謝各位的閱讀!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-17發表,共計4448字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 洛浦县| 平阳县| 卢氏县| 兴国县| 临邑县| 吐鲁番市| 承德市| 齐齐哈尔市| 三河市| 积石山| 广西| 伊通| 宣城市| 育儿| 宜昌市| 舞阳县| 开远市| 凤凰县| 邢台市| 合阳县| 龙游县| 民丰县| 阿拉善盟| 昌都县| 武宁县| 德保县| 奎屯市| 怀安县| 武平县| 东港市| 本溪市| 吉木乃县| 化隆| 湟源县| 千阳县| 防城港市| 彭州市| 中牟县| 无为县| 右玉县| 临澧县|