您好,登錄后才能下訂單哦!
數(shù)據(jù)庫(kù)并發(fā)控制的作用及示例分析,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
1.數(shù)據(jù)庫(kù)并發(fā)控制的作用
1.1 事務(wù)的概念
在介紹并發(fā)控制前,首先需要了解事務(wù)。數(shù)據(jù)庫(kù)提供了增刪改查等幾種基礎(chǔ)操作,用戶可以靈活地組合這幾種操作,實(shí)現(xiàn)復(fù)雜的語(yǔ)義。在很多場(chǎng)景下,用戶希望一組操作可以做為一個(gè)整體一起生效,這就是事務(wù)。事務(wù)是數(shù)據(jù)庫(kù)狀態(tài)變更的基本單元,包含一個(gè)或多個(gè)操作(例如多條SQL語(yǔ)句)。經(jīng)典的轉(zhuǎn)賬事務(wù),就包括三個(gè)操作:(1)檢查A賬戶余額是否足夠。(2)如果足夠,從A扣減100塊。(3)B賬戶增加100塊。
事務(wù)有個(gè)基本特性:這一組操作要么一起生效,要么都不生效,事務(wù)執(zhí)行過(guò)程中如遇錯(cuò)誤,已經(jīng)執(zhí)行的操作要全部撤回,這就是事務(wù)的原子性。如果失敗發(fā)生后,部分生效的事務(wù)無(wú)法撤回,那數(shù)據(jù)庫(kù)就進(jìn)入了不一致?tīng)顟B(tài),與真實(shí)世界的事實(shí)相左。例如轉(zhuǎn)賬事務(wù)從A賬戶扣款100塊后失敗了,B賬戶還未增加款項(xiàng),如果A賬戶扣款操作未撤回,這個(gè)世界就莫名奇妙丟失了100塊。原子性可以通過(guò)記日志(更改前的值)來(lái)實(shí)現(xiàn),還有一些數(shù)據(jù)庫(kù)將事務(wù)操作緩存在本地,如遇失敗,直接丟棄緩存里的操作。
事務(wù)只要提交了,它的結(jié)果就不能改變了,即使遇到系統(tǒng)宕機(jī),重啟后數(shù)據(jù)庫(kù)的狀態(tài)與宕機(jī)前一致,這就是事務(wù)的持久性。數(shù)據(jù)只要存儲(chǔ)非易失存儲(chǔ)介質(zhì),宕機(jī)就不會(huì)導(dǎo)致數(shù)據(jù)丟失。因此數(shù)據(jù)庫(kù)可以采用以下方法來(lái)保證持久性:(1)事務(wù)完成前,所有的更改都保證存儲(chǔ)到磁盤上了。或(2)提交完成前,事務(wù)的更改信息,以日志的形式存儲(chǔ)在磁盤,重啟過(guò)程根據(jù)日志恢復(fù)出數(shù)據(jù)庫(kù)系統(tǒng)的內(nèi)存狀態(tài)。一般而言,數(shù)據(jù)庫(kù)會(huì)選擇方法(2),原因留給讀者思考。
數(shù)據(jù)庫(kù)為了提高資源利用率和事務(wù)執(zhí)行效率、降低響應(yīng)時(shí)間,允許事務(wù)并發(fā)執(zhí)行。但是多個(gè)事務(wù)同時(shí)操作同一對(duì)象,必然存在沖突,事務(wù)的中間狀態(tài)可能暴露給其它事務(wù),導(dǎo)致一些事務(wù)依據(jù)其它事務(wù)中間狀態(tài),把錯(cuò)誤的值寫到數(shù)據(jù)庫(kù)里。需要提供一種機(jī)制,保證事務(wù)執(zhí)行不受并發(fā)事務(wù)的影響,讓用戶感覺(jué),當(dāng)前仿佛只有自己發(fā)起的事務(wù)在執(zhí)行,這就是隔離性。隔離性讓用戶可以專注于單個(gè)事務(wù)的邏輯,不用考慮并發(fā)執(zhí)行的影響。數(shù)據(jù)庫(kù)通過(guò)并發(fā)控制機(jī)制保證隔離性。由于隔離性對(duì)事務(wù)的執(zhí)行順序要求較高,很多數(shù)據(jù)庫(kù)提供了不同選項(xiàng),用戶可以犧牲一部分隔離性,提升系統(tǒng)性能。這些不同的選項(xiàng)就是事務(wù)隔離級(jí)別。
數(shù)據(jù)庫(kù)反映的是真實(shí)世界,真實(shí)世界有很多限制,例如:賬戶之間無(wú)論怎么轉(zhuǎn)賬,總額不會(huì)變等現(xiàn)實(shí)約束;年齡不能為負(fù)值,性別最多只能有男、女、跨性別者三種選項(xiàng)等完整性約束。事務(wù)執(zhí)行,不能打破這些約束,保證事務(wù)從一個(gè)正確的狀態(tài)轉(zhuǎn)移到另一個(gè)正確的狀態(tài),這就是一致性。不同與前三種性質(zhì)完全由數(shù)據(jù)庫(kù)實(shí)現(xiàn)保證,一致性既依賴于數(shù)據(jù)庫(kù)實(shí)現(xiàn)(原子性、持久性、隔離性也是為了保證一致性),也依賴于應(yīng)用端編寫的事務(wù)邏輯。
1.2 事務(wù)并發(fā)控制如何保證隔離性
為了保證隔離性,一種方式是所有事務(wù)串行執(zhí)行,讓事務(wù)之間不互相干擾。但是串行執(zhí)行效率非常低,為了增大吞吐,減小響應(yīng)時(shí)間,數(shù)據(jù)庫(kù)通常允許多個(gè)事務(wù)同時(shí)執(zhí)行。因此并發(fā)控制模塊需要保證:事務(wù)并發(fā)執(zhí)行的效果,與事務(wù)串行執(zhí)行的效果完全相同(serializability),以達(dá)到隔離性的要求。
為了方便描述并發(fā)控制如何保證隔離性,我們簡(jiǎn)化事務(wù)模型。事務(wù)是由一個(gè)或多個(gè)操作組成,所有的操作最終都可以拆分為一系列讀和寫。一批同時(shí)發(fā)生的事務(wù),所有讀、寫的一種執(zhí)行順序,被定義為一個(gè)schedule,例如:
T1、T2同時(shí)執(zhí)行,一個(gè)可能的schedule: T1.read(A),T2.read(B),T1.write(A),T1.read(B),T2.write(A)
如果并發(fā)事務(wù)執(zhí)行的schedule效果與串行執(zhí)行的schedule(serial schedule)等價(jià),就可以滿足serializability。一個(gè)schedule不斷調(diào)換讀寫操作的順序,總會(huì)變成一個(gè)serializable schedule,但是有的調(diào)換可能導(dǎo)致事務(wù)執(zhí)行的結(jié)果不一樣。一個(gè)schedule中,相鄰的兩個(gè)操作調(diào)換位置導(dǎo)致事務(wù)結(jié)果變化,那么這兩個(gè)操作就是沖突的。沖突需要同時(shí)滿足以下條件:
1.這兩個(gè)操作來(lái)自不同事務(wù)
2.至少有一個(gè)是寫操作
3.操作對(duì)象相同
因此常見(jiàn)的沖突包括:
讀寫沖突。事務(wù)先A讀取某行數(shù)據(jù)、事務(wù)B后修改該行數(shù)據(jù),和事務(wù)B先修改某行事務(wù)、事務(wù)A后讀該行記錄兩種schedule。事務(wù)A讀到的結(jié)果不同。這種沖突可能會(huì)導(dǎo)致不可重復(fù)讀異象和臟讀異象。
寫讀沖突。與讀寫沖突產(chǎn)生的原因相同。這種沖突可能會(huì)導(dǎo)致臟讀異象。
寫寫沖突。兩個(gè)操作先后寫一個(gè)對(duì)象,后一個(gè)操作的結(jié)果決定了寫入的最終結(jié)果。這種沖突可能會(huì)導(dǎo)致更新丟失異象。
數(shù)據(jù)庫(kù)只要保證,并發(fā)事務(wù)的schedule,保持沖突操作的執(zhí)行順序不變,只調(diào)換不沖突的操作,可以成為serial schedule,就可以認(rèn)為它們等價(jià)。這種等價(jià)判斷方式叫做conflict equivalent:兩個(gè)schedule的沖突操作順序相同。例如下圖的例子,T1 write(A)與T3 read(A)沖突,且T1先于T3發(fā)生。T1 read(B)和 T2 write(B)沖突,且T2先于T1,因此左圖事務(wù)執(zhí)行的schedule,與T2,T1,T3串行執(zhí)行的serial schedule(右圖) 等價(jià)。左圖的執(zhí)行順序滿足conflict serializablity。
再分析一個(gè)反例:T1 read(A)與T2 write(A)沖突且T1先于T2,T2 write(A)與T2 write(A)沖突且T2先于T1。下圖這個(gè)個(gè)schedule無(wú)法與任何一個(gè)serial schedule等價(jià),是一個(gè)不滿足conflict serializablity的執(zhí)行順序,會(huì)造成更新丟失的異象。
總體來(lái)說(shuō),serializability是比較嚴(yán)格的要求,為了提高數(shù)據(jù)庫(kù)系統(tǒng)的并發(fā)性能,很多用戶愿意去降低隔離性的要求以尋求更好的性能。數(shù)據(jù)庫(kù)系統(tǒng)往往會(huì)實(shí)現(xiàn)多種隔離級(jí)別,供用戶靈活選擇,關(guān)于事務(wù)隔離級(jí)別,可以參看這篇文章。
并發(fā)控制的要求清楚了,如何實(shí)現(xiàn)呢?后文將依據(jù)沖突檢測(cè)的樂(lè)觀程度,一一介紹并發(fā)控制常見(jiàn)的實(shí)現(xiàn)方法。
2.基于兩階段鎖的并發(fā)控制
2.1 2PL
既然要保證操作按正確的順序執(zhí)行,最容易想到的方法就是加鎖保護(hù)訪問(wèn)對(duì)象。數(shù)據(jù)庫(kù)系統(tǒng)的鎖管理器模塊,專門負(fù)責(zé)給訪問(wèn)對(duì)象加鎖和釋放鎖,保證只有持有鎖的事務(wù),才能操作相應(yīng)的對(duì)象。鎖可以分為兩類:S-Lock和X-Lock,S-Lock是讀請(qǐng)求使用的共享鎖,X-Lock是寫請(qǐng)求使用的排他鎖。它們的兼容性如下:操作同一個(gè)對(duì)象,只有兩個(gè)讀請(qǐng)求相互兼容,可以同時(shí)執(zhí)行,讀寫和寫寫操作都會(huì)因?yàn)殒i沖突而串行執(zhí)行。
2PL(Two-phase locking)是數(shù)據(jù)庫(kù)最常見(jiàn)的基于鎖的并發(fā)控制協(xié)議,顧名思義,它包含兩個(gè)階段:
階段一:Growing,事務(wù)向鎖管理器請(qǐng)求它需要的所有鎖(存在加鎖失敗的可能)。
階段二:Shrinking,事務(wù)釋放Growing階段獲取的鎖,不允許再請(qǐng)求新鎖。
為什么加鎖和放鎖要涇渭分明地分為兩個(gè)階段呢?
2PL并發(fā)控制目的是為了達(dá)到serializable,如果并發(fā)控制不事先將所有需要的鎖申請(qǐng)好,而是釋放鎖后,還允許再次申請(qǐng)鎖,可能出現(xiàn)事務(wù)內(nèi)兩次操作同一對(duì)象之間,其它事務(wù)修改這一對(duì)象(如下圖所示),進(jìn)而無(wú)法達(dá)到conflict serializable,出現(xiàn)不一致的現(xiàn)象(下面的例子是lost update)。
2PL可以保證conflict serializability,因?yàn)槭聞?wù)必須拿到所有需要的鎖才能執(zhí)行。例如正在執(zhí)行的事務(wù)A與事務(wù)B沖突,事務(wù)B要么已經(jīng)執(zhí)行完,要么還在等待。因此那些沖突操作的執(zhí)行順序,與BA或AB串行執(zhí)行時(shí)沖突操作執(zhí)行順序一致。
所以,數(shù)據(jù)庫(kù)只要采用2PL就能保證一致性和隔離性了嗎?來(lái)看一下這個(gè)例子:
以上執(zhí)行順序是符合2PL的,但T2讀到了未提交的數(shù)據(jù)。如果此時(shí)T1回滾,則會(huì)引發(fā)級(jí)聯(lián)回滾(T1的更改,不能被任何事務(wù)看到)。因此,數(shù)據(jù)庫(kù)往往使用的是加強(qiáng)版的S(trong)S(trict)2PL,它相較于2PL有一點(diǎn)不同:shrinking階段,只能在事務(wù)結(jié)束后再釋放鎖,完全杜絕了事務(wù)未提交的數(shù)據(jù)被讀到。
2.2 死鎖處理
并發(fā)事務(wù)加鎖放鎖必然繞不開(kāi)一個(gè)問(wèn)題--死鎖:事務(wù)1持有A鎖等B鎖,事務(wù)2持有B鎖等A鎖。目前解決死鎖問(wèn)題有兩種方案:
Deadlock Detection:
數(shù)據(jù)庫(kù)系統(tǒng)根據(jù)waits-for圖記錄事務(wù)的等待關(guān)系,其中點(diǎn)代表事務(wù),有向邊代表事務(wù)在等待另一個(gè)事務(wù)放鎖。當(dāng)waits-for圖出現(xiàn)環(huán)時(shí),代表死鎖出現(xiàn)了。系統(tǒng)后臺(tái)會(huì)定時(shí)檢測(cè)waits-for圖,如果發(fā)現(xiàn)環(huán),則需要選擇一個(gè)合適的事務(wù)abort。
Deadlock Prevention:
當(dāng)事務(wù)去請(qǐng)求一個(gè)已經(jīng)被持有的鎖時(shí),數(shù)據(jù)庫(kù)系統(tǒng)為防止死鎖,殺死其中一個(gè)事務(wù)(一般持續(xù)越久的事務(wù),保留的優(yōu)先級(jí)越高)。這種防患于未然的方法不需要waits-for圖,但提高了事務(wù)被殺死的比率。
2.3 意向鎖
如果只有行鎖,那么事務(wù)要更新一億條記錄,需要獲取一億個(gè)行鎖,將占用大量的內(nèi)存資源。我們知道鎖是用來(lái)保護(hù)數(shù)據(jù)庫(kù)內(nèi)部訪問(wèn)對(duì)象的,這些對(duì)象根據(jù)大小可能是:屬性(Attribute)、記錄(Tuple)、頁(yè)面(Page)、表(Table),相應(yīng)的鎖可分為行鎖、頁(yè)面鎖、表鎖(沒(méi)人實(shí)現(xiàn)屬性鎖,對(duì)于OLTP數(shù)據(jù)庫(kù),最小的操作單元是行)。對(duì)于事務(wù)來(lái)講,獲得最少量的鎖當(dāng)然是最好的,比如更新一億條記錄,或許加一個(gè)表鎖就足夠了。
層次越高的鎖(如表鎖),可以有效減少對(duì)資源的占用,顯著減少鎖檢查的次數(shù),但會(huì)嚴(yán)重限制并發(fā)。層次越低的鎖(如行鎖),有利于并發(fā)執(zhí)行,但在事務(wù)請(qǐng)求對(duì)象多的情況下,需要大量的鎖檢查。數(shù)據(jù)庫(kù)系統(tǒng)為了解決高層次鎖限制并發(fā)的問(wèn)題,引入了意向(Intention)鎖的概念:
Intention-Shared (IS):表明其內(nèi)部一個(gè)或多個(gè)對(duì)象被S-Lock保護(hù),例如某表加IS,表中至少一行被S-Lock保護(hù)。
Intention-Exclusive (IX):表明其內(nèi)部一個(gè)或多個(gè)對(duì)象被X-Lock保護(hù)。例如某表加IX,表中至少一行被X-Lock保護(hù)。
Shared+Intention-Exclusive (SIX):表明內(nèi)部至少一個(gè)對(duì)象被X-Lock保護(hù),并且自身被S-Lock保護(hù)。例如某個(gè)操作要全表掃描,并更改表中幾行,可以給表加SIX。讀者可以思考一下,為啥沒(méi)有XIX或XIS
意向鎖和普通鎖的兼容關(guān)系如下所示:
意向鎖的好處在于:當(dāng)表加了IX,意味著表中有行正在修改。(1)這時(shí)對(duì)表發(fā)起DDL操作,需要請(qǐng)求表的X鎖,那么看到表持有IX就直接等待了,而不用逐個(gè)檢查表內(nèi)的行是否持有行鎖,有效減少了檢查開(kāi)銷。(2)這時(shí)有別的讀寫事務(wù)過(guò)來(lái),由于表加的是IX而非X,并不會(huì)阻止對(duì)行的讀寫請(qǐng)求(先在表上加IX,再去記錄上加S/X),事務(wù)如果沒(méi)有涉及已經(jīng)加了X鎖的行,則可以正常執(zhí)行,增大了系統(tǒng)的并發(fā)度。
3.基于Timing Order(T/O)的并發(fā)控制
為每個(gè)事務(wù)分配timestamp,并以此決定事務(wù)執(zhí)行順序。當(dāng)事務(wù)1的timestamp小于事務(wù)2時(shí),數(shù)據(jù)庫(kù)系統(tǒng)要保證事務(wù)1先于事務(wù)2執(zhí)行。timestamp分配的方式包括:(1)物理時(shí)鐘;(2)邏輯時(shí)鐘;(2)混合時(shí)鐘。
3.1 Basic T/O
基于T/O的并發(fā)控制,讀寫不需加鎖, 每行記錄都標(biāo)記了最后修改和讀取它的事務(wù)的timestamp。當(dāng)事務(wù)的timestamp小于記錄的timestamp時(shí)(不能讀到”未來(lái)的”數(shù)據(jù)),需要abort后重新執(zhí)行。假設(shè)記錄X上標(biāo)記了讀寫兩個(gè)timestamp:WTS(X)和RTS(X),事務(wù)的timestamp為TTS,可見(jiàn)性判斷如下:
讀:
TTS < WTS(X):該對(duì)象對(duì)該事務(wù)不可見(jiàn),abort事務(wù),取一個(gè)新timestamp重新開(kāi)始。
TTS > WTS(X):該對(duì)象對(duì)事務(wù)可見(jiàn),更新RTS(X) = max(TTS,RTS(X))。為了滿足repeatable read,事務(wù)復(fù)制X的值。
為了防止讀到臟數(shù)據(jù),可以在記錄上做特殊標(biāo)記,讀請(qǐng)求需等待事務(wù)提交后再去讀。
寫:
TTS < WTS(X) || TTS < RTS(X):abort事務(wù),重新開(kāi)始。
TTS > WTS(X) && TTS > RTS(X): 事務(wù)更新X,WTS(X) = TTS。
這里之所以要求TTS > RTS(X),是為了防止如下情況:讀請(qǐng)求的時(shí)間戳為rts,已經(jīng)讀過(guò)X,時(shí)間戳設(shè)為RTS(X)=rts,如果新事務(wù)的TTS < RTS(X),并且更新成功,則rts讀請(qǐng)求再來(lái)讀一次就看到新的更改了,違反了repeatable read,因此這是為了避免讀寫沖突。記錄上存儲(chǔ)了最后的讀寫時(shí)間,可以保證conflict serializable
這種方式也能避免write skew,例如:初始狀態(tài),X和Y兩條記錄,X=-3,Y=5,X+Y >0,RTS(X)=RTS(Y)=WTS(X)=WTS(Y)=0。事務(wù)T1的時(shí)間戳為TTS1=1,事務(wù)T2的時(shí)間戳TTS2=2。
它缺陷包括:
長(zhǎng)事務(wù)容易餓死,因?yàn)殚L(zhǎng)事務(wù)的timestamp偏小,大概率會(huì)在執(zhí)行一段時(shí)間后讀到更新的數(shù)據(jù),導(dǎo)致abort。
讀操作也會(huì)產(chǎn)生寫(寫RTS)。
4.基于Validation(OCC)的并發(fā)控制
執(zhí)行過(guò)程中,每個(gè)事務(wù)維護(hù)自己的寫操作(Basic T/O在事務(wù)執(zhí)行過(guò)程中寫就將數(shù)據(jù)寫入DB)和相應(yīng)的RTS/WTS,提交時(shí)判斷自己的更改是否和數(shù)據(jù)庫(kù)中已存在的數(shù)據(jù)沖突,如果不沖突才寫入DB。OCC分為三個(gè)階段:
Read & Write Phase:即讀寫階段,事務(wù)維護(hù)讀的結(jié)果和即將提交的更改,以及寫入記錄的RTS和WTS。
Validation Phase:檢查事務(wù)是否與數(shù)據(jù)庫(kù)中的數(shù)據(jù)沖突。
Write Phase:不沖突就寫入,沖突就abort,restart。
Read & Write Phase結(jié)束,進(jìn)入Validation Phase相當(dāng)于事務(wù)準(zhǔn)備完成,進(jìn)入提交階段了,進(jìn)入Validation Phase的時(shí)間被選做記錄行的時(shí)間戳,來(lái)定序。不用事務(wù)開(kāi)始時(shí)間是因?yàn)椋菏聞?wù)執(zhí)行時(shí)間可能較長(zhǎng),導(dǎo)致后開(kāi)始的事務(wù)可能先提交,這會(huì)加大事務(wù)沖突的概率,較小時(shí)間戳的事務(wù)后寫入數(shù)據(jù)庫(kù),肯定會(huì)abort。
Validation過(guò)程
假設(shè)當(dāng)前只有兩個(gè)事務(wù)T1和T2,并修改了相同數(shù)據(jù)行,T1的時(shí)間戳 < T2的時(shí)間戳(即validation順序:T1 < T2,對(duì)用戶而言,T1先發(fā)生于T2),則有如下情況:
(1)T1在validate階段,T2還在Read & Write Phase。此時(shí)只要T1和T2已經(jīng)發(fā)生的讀寫沒(méi)有沖突,就可以提交。
如果WS(T1) ∩ (RS(T2) ∪ WS(T2)) = ∅,說(shuō)明T2和T1寫的記錄無(wú)沖突,validation通過(guò),可以寫入。
否則,T2與T1之間存在讀寫沖突或?qū)憣憶_突,T1需要回滾。讀寫沖突:T2讀到了T1寫之前的版本,T1提交后,它可能讀到T1寫的版本,不可重復(fù)讀。寫寫沖突:T2有可能在舊版本基礎(chǔ)上更新,再次寫入,造成T1的更新丟失。
(2)T1完成validate階段,進(jìn)入write階段直到提交完成,這已經(jīng)是不可逆的了。T2在T1進(jìn)入write phase之前的讀寫,肯定和T1的操作不沖突(因?yàn)門1 validation通過(guò)了)。T2之后繼續(xù)的讀寫操作,有可能沖突與T1要提交的操作,因此T2進(jìn)入validate階段:
如果WS(T1) ∩ RS(T2)= ∅,說(shuō)明T2沒(méi)讀到T1寫的記錄,validation通過(guò),T2可以寫入。(為什么不驗(yàn)證WS(T2)了呢?WS(T1)已經(jīng)提交了,且它的時(shí)間戳小于WS(T2),WS(T2)里之前的一部分肯定沒(méi)有沖突,之后的一部分,因?yàn)闆](méi)有讀過(guò)T1的寫入的對(duì)象,寫進(jìn)去也沒(méi)問(wèn)題,不會(huì)覆蓋WS(T1)的寫)
否則,T2與T1之間存在讀寫沖突和寫寫沖突,T2需要回滾。讀寫沖突:T2讀到了T1寫之前的版本,T1提交后,它可能讀到T1寫的版本,不可重復(fù)讀。寫寫沖突:T2有可能在舊版本基礎(chǔ)上更新,再次寫入,造成T1的更新丟失。
5.基于MVCC的并發(fā)控制
數(shù)據(jù)庫(kù)維護(hù)了一條記錄的多個(gè)物理版本。事務(wù)寫入時(shí),創(chuàng)建寫入數(shù)據(jù)的新版本,讀請(qǐng)求依據(jù)事務(wù)/語(yǔ)句開(kāi)始時(shí)的快照信息,獲取當(dāng)時(shí)已經(jīng)存在的最新版本數(shù)據(jù)。它帶來(lái)的最直接的好處是:寫不阻塞讀,讀也不阻塞寫,讀請(qǐng)求永遠(yuǎn)不會(huì)因此沖突失敗(例如單版本T/O)或者等待(例如單版本2PL)。對(duì)數(shù)據(jù)庫(kù)請(qǐng)求來(lái)說(shuō),讀請(qǐng)求往往多于寫請(qǐng)求。主流的數(shù)據(jù)庫(kù)幾乎都采用了這項(xiàng)優(yōu)化技術(shù)。
MVCC是讀和寫請(qǐng)求的優(yōu)化技術(shù),沒(méi)有完全解決數(shù)據(jù)庫(kù)并發(fā)問(wèn)題,它需要與前述的幾種并發(fā)控制技術(shù)組合,才能提供完整的并發(fā)控制能力。常見(jiàn)的并發(fā)控制技術(shù)種類包括:MV-2PL,MV-T/O和MV-OCC,它們的特點(diǎn)如下表:
MVCC還有兩個(gè)關(guān)鍵點(diǎn)需要考慮:多版本數(shù)據(jù)的存儲(chǔ)和多余多版本數(shù)據(jù)的回收。
多版本數(shù)據(jù)存儲(chǔ)方式,大致可以分為兩類:(1)Append only的方式,新舊版本存儲(chǔ)在同一個(gè)表空間,例如基于LSM-Tree的存儲(chǔ)引擎。(2)主表空間記錄最新版本數(shù)據(jù),前鏡像記錄在其它表空間或數(shù)據(jù)段,例如InnoDB的多版本信息記錄在undo log。多版本數(shù)據(jù)回收又稱為垃圾回收(GC),那些沒(méi)有機(jī)會(huì)再被任何讀請(qǐng)求獲取的舊版本記錄,應(yīng)該被及時(shí)刪除。
依據(jù)沖突處理的時(shí)機(jī)(樂(lè)觀程度),依次介紹了基于鎖(在事務(wù)開(kāi)始前預(yù)防沖突)、基于T/O(在事務(wù)執(zhí)行中判斷沖突)和基于Validation(在事務(wù)提交時(shí)驗(yàn)證沖突)的事務(wù)并發(fā)控制機(jī)制。不同的實(shí)現(xiàn)適用于不同的workload,并發(fā)沖突小的workload,當(dāng)然適合更樂(lè)觀的并發(fā)控制方式。而MVCC可以解決只讀事務(wù)和讀寫事務(wù)之間相互阻塞的問(wèn)題,提高了事務(wù)的并發(fā)讀,被大多數(shù)主流數(shù)據(jù)庫(kù)系統(tǒng)采用。
看完上述內(nèi)容,你們掌握數(shù)據(jù)庫(kù)并發(fā)控制的作用及示例分析的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。