第八章系統(tǒng)故障對策
本章主要講支持可恢復(fù)性這一目標(biāo)的相應(yīng)技術(shù)横殴,可恢復(fù)性是指系統(tǒng)發(fā)生某些故障時的數(shù)據(jù)完整性锰扶。支持可恢復(fù)性的基礎(chǔ)技術(shù)是日志尺碰,日志以一種安全的方式記錄數(shù)據(jù)的變更歷史梯码。
本章主要討論以下幾個問題:
- 數(shù)據(jù)庫日志辛孵,通常有三種不同的數(shù)據(jù)庫系統(tǒng)日志(undo,redo,undo/redo)
- 故障恢復(fù)牌捷,恢復(fù)是故障發(fā)生后使用日志重建對數(shù)據(jù)庫所作更新的過程墙牌。
- 檢查點,避免追溯到很久以前的日志暗甥。
- 數(shù)據(jù)備份喜滨,它使得數(shù)據(jù)庫不僅能經(jīng)受暫時的系統(tǒng)故障,并且能夠經(jīng)受數(shù)據(jù)庫丟失的情況撤防。
一虽风、數(shù)據(jù)庫故障模式
我們從可能發(fā)生的各種問題及數(shù)據(jù)庫管理系統(tǒng)針對這些問題能做什么,該做什么著手討論如何應(yīng)對故障寄月。下面列出最重要的故障模式及DBMS對這些故障所能采取的措施:
-
錯誤數(shù)據(jù)輸入
例如:電話號碼少輸入了一位辜膝。這種錯誤通常無法被檢測到。
措施:通過編寫約束或觸發(fā)器來防范漾肮。 -
介質(zhì)故障
例如:磁盤一位或少數(shù)幾位故障厂抖,通過磁盤扇區(qū)的奇偶校驗可檢測到。
措施:使用某種RAID模式克懊;維護一個備份忱辅;聯(lián)機保存數(shù)據(jù)庫的冗余拷貝。 -
災(zāi)難性故障
例如:火災(zāi)谭溉,爆炸墙懂,惡意破壞。
措施:可采用防范介質(zhì)故障中的維護一個備份和聯(lián)機保存數(shù)據(jù)庫的冗余拷貝夜只。 -
系統(tǒng)故障
例如:掉電和軟件錯誤等導(dǎo)致事物狀態(tài)丟失垒在。
措施:在分離的、非易失的日志中記錄所有數(shù)據(jù)庫更新扔亥,必要時加以恢復(fù)。這正是我們馬上要討論的數(shù)據(jù)庫日志機制建立的原因谈为。
二旅挤、數(shù)據(jù)庫事物(Database Transaction)
事物是指用戶定義的一個數(shù)據(jù)庫操作序列,它是數(shù)據(jù)庫操作執(zhí)行的基本單位伞鲫,要么全部執(zhí)行成功要么全部執(zhí)行失敗粘茄。
1. ACID
數(shù)據(jù)庫引入事物是為了保證數(shù)據(jù)操作的ACID(Atomicity,Consistency,Isolation,Durability)特性:
a. 原子性(atomicity)
事務(wù)必須是原子工作單元;對于其數(shù)據(jù)修改,要么全都執(zhí)行柒瓣,要么全都不執(zhí)行儒搭。通常,與某個事務(wù)關(guān)聯(lián)的操作具有共同的目標(biāo)芙贫,并且是相互依賴的搂鲫。如果系統(tǒng)只執(zhí)行這些操作的一個子集,則可能會破壞事務(wù)的總體目標(biāo)磺平。原子性消除了系統(tǒng)處理操作子集的可能性魂仍。
b. 一致性(consistency)
事務(wù)在完成時,必須使所有的數(shù)據(jù)都保持一致狀態(tài)拣挪。在相關(guān)數(shù)據(jù)庫中擦酌,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性菠劝。事務(wù)結(jié)束時赊舶,所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如 B 樹索引或雙向鏈表)都必須是正確的。某些維護一致性的責(zé)任由應(yīng)用程序開發(fā)人員承擔(dān)赶诊,他們必須確保應(yīng)用程序已強制所有已知的完整性約束笼平。例如,當(dāng)開發(fā)用于轉(zhuǎn)帳的應(yīng)用程序時甫何,應(yīng)避免在轉(zhuǎn)帳過程中任意移動小數(shù)點出吹。
c. 隔離性(isolation)
由并發(fā)事務(wù)所作的修改必須與任何其它并發(fā)事務(wù)所作的修改隔離。事務(wù)查看數(shù)據(jù)時數(shù)據(jù)所處的狀態(tài)辙喂,要么是另一并發(fā)事務(wù)修改它之前的狀態(tài)捶牢,要么是另一事務(wù)修改它之后的狀態(tài),事務(wù)不會查看中間狀態(tài)的數(shù)據(jù)巍耗。這稱為可串行性秋麸,因為它能夠重新裝載起始數(shù)據(jù),并且重播一系列事務(wù)炬太,以使數(shù)據(jù)結(jié)束時的狀態(tài)與原始事務(wù)執(zhí)行的狀態(tài)相同灸蟆。當(dāng)事務(wù)可序列化時將獲得最高的隔離級別。在此級別上亲族,從一組可并行執(zhí)行的事務(wù)獲得的結(jié)果與通過連續(xù)運行每個事務(wù)所獲得的結(jié)果相同炒考。由于高度隔離會限制可并行執(zhí)行的事務(wù)數(shù),所以一些應(yīng)用程序降低隔離級別以換取更大的吞吐量霎迫。防止數(shù)據(jù)丟失斋枢。
d. 持久性(Duration)
事務(wù)完成之后,它對于系統(tǒng)的影響是永久性的知给。該修改即使出現(xiàn)致命的系統(tǒng)故障也將一直保持瓤帚。
2. 事物管理器和日志管理器
查詢處理器 <-- 事物管理器 --> 日志管理器
\ | /
緩沖區(qū)管理器 <--> 恢復(fù)管理器
|
數(shù)據(jù)庫日志
- 事物管理器:保證并發(fā)執(zhí)行的事務(wù)互不干擾描姚,都能夠正確執(zhí)行。
- 事物管理器-->查詢處理器: 事物管理器告訴查詢處理器使之能夠執(zhí)行查詢以及其它構(gòu)成事物的數(shù)據(jù)庫操作戈次。
- 事物管理器-->日志管理器: 事物管理器將關(guān)于事物動作的消息傳遞給日志管理器轩勘,使必需的信息能以“日志記錄”的形式存儲在日志中。
- 事物管理器-->緩沖區(qū)管理器:事物管理器將何時可以或者必須將緩沖區(qū)拷貝回磁盤的消息傳遞給緩沖區(qū)管理器怯邪。
- 日志管理器:日志管理器維護日志绊寻。
- 恢復(fù)管理器:日志和數(shù)據(jù)一樣占用磁盤上的空間。當(dāng)發(fā)生數(shù)據(jù)庫系統(tǒng)崩潰時擎颖,恢復(fù)管理器就被激活榛斯,它檢查日志并在必要時利用日志恢復(fù)數(shù)據(jù)。
3. 事物的正確執(zhí)行
數(shù)據(jù)庫的一致性狀態(tài)必須滿足數(shù)據(jù)庫模式的所有約束(實體完整性約束搂捧,參照完整性約束驮俗,用戶定義的完整性約束)。
事物執(zhí)行的正確性原則:如果事物在沒有其它任何事物和系統(tǒng)錯誤的情況下執(zhí)行允跑,并且在它開始執(zhí)行時數(shù)據(jù)庫處于一致的狀態(tài)王凑,那么事物結(jié)束時數(shù)據(jù)庫仍然處于一致的狀態(tài)。
4. 事物的原語操作
數(shù)據(jù)在數(shù)據(jù)庫系統(tǒng)中主要有三個地址空間:
- 保持?jǐn)?shù)據(jù)庫元素的磁盤塊空間
- 緩沖區(qū)管理器所管理的虛存或主存地址空間
- 事務(wù)的局部地址空間
事物要讀取數(shù)據(jù)庫元素聋丝,首先必須從磁盤被讀取到主存的緩沖區(qū)中索烹,然后再從緩沖區(qū)讀取到事物的局部地址空間。事物的寫入剛好與此相反弱睦。
為了研究日志的方便我們定義一種記法來描述所有使數(shù)據(jù)在地址空間之間移動的操作:
- INPUT(X): 將包含數(shù)據(jù)庫元素的磁盤塊拷貝到主存緩沖區(qū)百姓。
- READ(X, t): 將數(shù)據(jù)庫元素X拷貝到事物的局部變量t。
- WRITE(X况木,t): 將事物局部變量t的值拷貝到主存緩沖區(qū)中的數(shù)據(jù)庫元素X垒拢。
- OUTPUT(X): 將包含X的緩沖區(qū)中的塊拷貝回磁盤。
例如:事物T邏輯上由下述兩步構(gòu)成:
A:= A × 2
B:= B × 2
我們可以將T描述為如下幾個相關(guān)步驟:
READ(A, t); t:=t*2; WRITE(A, t);
READ(B, t); t:=t*2; WRITE(B, t);
詳細表述為(假設(shè)A=B=8):
動作 | t | 內(nèi)存中的A | 磁盤中的A | 內(nèi)存中的B | 磁盤中的B |
---|---|---|---|---|---|
INPUT(A) | 8 | 8 | 8 | ||
READ(A, t) | 8 | 8 | 8 | 8 | |
t:=t*2 | 16 | 8 | 8 | 8 | |
WRITE(A, t) | 16 | 16 | 8 | 8 | |
INPUT(B) | 16 | 16 | 8 | 8 | 8 |
READ(B, t) | 8 | 16 | 8 | 8 | 8 |
t:=t*2 | 16 | 16 | 8 | 8 | 8 |
WRITE(B,t) | 16 | 16 | 8 | 16 | 8 |
OUTPUT(A) | 16 | 16 | 16 | 16 | 8 |
OUTPUT(B) | 16 | 16 | 16 | 16 | 16 |
不難發(fā)現(xiàn)火惊,只要所有的這些步驟都執(zhí)行求类,數(shù)據(jù)庫的一致性狀態(tài)就能夠保持,但如果系統(tǒng)故障發(fā)生在了OUTPUT(A)之后和OUTPUT(B)之前屹耐。數(shù)據(jù)庫就會處于不一致的狀態(tài)了尸疆。
我們不能防止這種情況發(fā)生,但我們可以在這種情況發(fā)生時進行修復(fù)——要么A和B都被重置為8惶岭,要么都被更新為16寿弱。
三、數(shù)據(jù)庫日志
日志是日志記錄以追加寫的方式構(gòu)成的文件按灶,每條日志記錄了有關(guān)某個事物已做的某些操作脖捻。日志管理器負責(zé)記錄數(shù)據(jù)庫的每個重要事件。當(dāng)數(shù)據(jù)庫系統(tǒng)崩潰時兆衅,我們可以用日志將數(shù)據(jù)庫恢復(fù)到一個一致性狀態(tài)。
日志記錄的幾種形式:
1) <START T>: 事務(wù)已經(jīng)開始。
2) <COMMIT T>: 事物已經(jīng)完成羡亩,并且不會在有修改操作摩疑。
3) <ABORT T>: 事物已中止,未能成功完成畏铆。
1 undo日志
undo日志雷袋,它通過撤銷事物在數(shù)據(jù)庫系統(tǒng)崩潰前還沒有來得及完成的操作來恢復(fù)數(shù)據(jù)庫的一致性狀態(tài)。
對于undo日志辞居,我們僅需要記錄更新記錄<T,X,v>,含義是:事物T修改了數(shù)據(jù)庫元素X楷怒,而X原來的值是v。更新記錄反映的是對主存的修改而不是對磁盤的修改瓦灶。
如果在使用undo日志的系統(tǒng)中需要進行恢復(fù)時鸠删,恢復(fù)管理器要做的唯一事情是通過恢復(fù)舊值消除事務(wù)可能在磁盤上造成的影響。簡單來說贼陶,undo日志不記錄數(shù)據(jù)庫元素的新值刃泡,而只記錄舊值。因此undo日志僅能夠還原磁盤改動而不能重做碉怔。
1.1 undo日志規(guī)則
U1: 如果事物改變了數(shù)據(jù)庫元素X烘贴,那么形如< T,X,v >的日志記錄必須在X的新值刷盤之前寫到磁盤。
U2: 如果事物提交撮胧,則其COMMIT日志記錄必須在事物改變的所有數(shù)據(jù)庫元素刷盤之后寫到磁盤桨踪,但應(yīng)盡快。
簡單來說是這么一個順序:日志刷盤->被改變的元素刷盤->最后COMMMIT記錄刷盤芹啥。
舉個例子:
步驟 | 動作 | t | Mem-A | Disk-A | Mem-B | Disk-B | 日志 |
---|---|---|---|---|---|---|---|
1) | < START T > | ||||||
2) | READ(A,t) | 8 | 8 | 8 | 8 | ||
3) | t:=t*2 | 16 | 8 | 8 | 8 | ||
4) | WRITE(A,t) | 16 | 16 | 8 | 8 | < T,A,8 > | |
5) | READ(B,t) | 8 | 16 | 8 | 8 | 8 | |
6) | t:=t*2 | 16 | 16 | 8 | 8 | 8 | |
7) | WRITE(B,t) | 16 | 16 | 8 | 16 | 8 | < T,B,8 > |
8) | FLUSH LOG | ||||||
9) | OUTPUT(A) | 16 | 16 | 16 | 16 | 8 | |
10) | OUTPUT(B) | 16 | 16 | 16 | 16 | 16 | |
11) | < COMMIT T > | ||||||
12) | FLUSH LOG |
那么問題來了
- DBMS會同時處理多個事物锻离,日志也是多個事物的日志混記在一起的,因此有可能由于別的事物的FLUSH LOG叁征,過早的將日志落盤纳账。但這對于undo日志沒有影響。
- 如果數(shù)據(jù)庫元素A和B在同一個數(shù)據(jù)塊內(nèi)捺疼,有可能由于其中一個元素的刷盤導(dǎo)致另一個元素過早的刷盤而違反規(guī)則U1疏虫。所以在使用undo日志的數(shù)據(jù)庫我們建議以數(shù)據(jù)塊為最小的封鎖單位。
1.2 使用undo日志進行故障恢復(fù)
假設(shè)此時數(shù)據(jù)庫系統(tǒng)發(fā)生了故障啤呼,有可能有一個最終尚未提交的事物卧秘,有些數(shù)據(jù)庫改動已經(jīng)落盤有的還沒有來得及落盤,這樣數(shù)據(jù)庫的狀態(tài)就不再一致了官扣。
恢復(fù)管理器必須使用日志來將數(shù)據(jù)庫從新恢復(fù)到某個一致的狀態(tài)翅敌。首先事物管理器從日志尾部開始向上掃描日志(這個順序是為了恢復(fù)到之前的一致狀態(tài)),掃描過程中記錄所有有< COMMIT T >和< ABORT T >記錄的事物T惕蹄,如果看見< T,X,v >則:
- 如果T是被COMMMIT過的蚯涮,則什么也不做治专。
- 如果T是一個未完成或者ABORT的事物,則直接將數(shù)據(jù)庫中X的值還原為v遭顶。
最后张峰,恢復(fù)管理器為每個未終止且未完成的事物T寫入一個< ABORT T >記錄,標(biāo)識事務(wù)已經(jīng)結(jié)束棒旗,然后刷新日志〈現(xiàn)在,數(shù)據(jù)庫就恢復(fù)正常了铣揉,新事物可以繼續(xù)執(zhí)行了饶深。
如果在恢復(fù)的過程中再次發(fā)生崩潰,由于undo日志的設(shè)計方式是冪等的逛拱,所以恢復(fù)操作多次執(zhí)行與一次執(zhí)行效果完全相同敌厘。
1.3 日志檢查點
1.3.1 靜止檢查點
理論上重放日志需要掃描整個日志文件,可是我們只關(guān)心未完成和中止的事物橘券,已經(jīng)COMMIT的事物日志是沒有用的(但是也不能刪除)额湘。我們采用周期性的對日志做檢查點:
- 停止接收新事物
- 等所有的活躍事物COMMIT或ABORT
- 將日志刷盤并寫入< CKPT >
- 開始接收新事物
活躍事物可能很長時間不能完成,導(dǎo)致新事物一直無法執(zhí)行旁舰,這是我們不能接受的锋华。
1.3.2 非靜止檢查點
在做非靜止檢查點時,不影響新事物執(zhí)行箭窜,它包括如下步驟:
- 記錄< START_CKPT(T1,T2,...,Tk) >并刷新日志毯焕,其中Ti表示當(dāng)前所有活躍事物。
- 等待T1...Tk全部都COMMIT或ABORT磺樱,此時允許新事物執(zhí)行纳猫。
- 當(dāng)T1...Tk都完成時記錄< END CKPT >并刷新日志。
日志回放時竹捉,從日志尾部向上掃描日志芜辕,恢復(fù)所有為提交事物的數(shù)據(jù)元素:
- 如果首先遇到< END_CKPT >,只需要回放日志到下一個< START_CKPT >為止块差,< START_CKPT >之前的日志可以丟棄侵续;
- 如果首先碰到的是< START_CKPT >, 只需要回放第一步中記錄的所有事務(wù)(T1,T2,...,Tk)最早開始的地方憨闰,再之前的日志記錄可以直接刪除状蜗。
第一種情況舉例:
<START T1>
<T1,A,5>
<START T2>
<T2,B,10>
<START CKPT(T1,T2)>
<T2,C,15>
<START T3>
<T1,D,20>
<COMMIT T1>
<T3,E,25>
<COMMIT T2>
<END CKPT>
<T3,F,30>
第二種情況舉例:
<START T1>
<T1,A,5>
<START T2>
<T2,B,10>
<START CKPT(T1,T2)>
<T2,C,15>
<START T3>
<T1,D,20>
<COMMIT T1>
<T3,E,25>
2 redo日志
undo日志有一個大問題,就是在我們將事物的數(shù)據(jù)庫元素的改動刷盤前鹉动,不能提交該事物轧坎。這就使得數(shù)據(jù)刷盤IO頻率很大,使用redo日志就可以避免這種頻繁刷盤泽示。
redo log是指在回放日志的時候把已經(jīng)commit的事務(wù)重做一遍缸血,對于沒有commit的事務(wù)按照abort處理蜜氨。日志回放并不會處理任何沒有commit的事務(wù), 因此属百,在COMMIT日志持久化之前记劝,不能將數(shù)據(jù)的修改持久化。因為如果數(shù)據(jù)在COMMIT之前持久化族扰,那么在系統(tǒng)異常退出的情況下,這種部分修改的事務(wù)就會處于一種不一致狀態(tài)定欧。同時渔呵,由于重做事務(wù),因此事務(wù)日志中必須記錄事務(wù)修改以后的值砍鸠。
2.1 redo日志和undo日志的主要區(qū)別
- undo日志記錄舊值扩氢,redo日志記錄新值。
- undo日志爷辱,恢復(fù)未完成事物录豺,忽略已完成事物。
- redo日志饭弓,忽略未完成事物双饥,重做已完成事物。
- undo日志弟断,所有事物改動數(shù)據(jù)先落盤咏花,后寫入COMMIT日志記錄。
- redo日志阀趴,先寫入COMMIT日志記錄昏翰,所有事物改動數(shù)據(jù)后落盤。
從數(shù)據(jù)和日志到達磁盤順序的角度可以說:數(shù)據(jù)修改日志都是先于數(shù)據(jù)落盤刘急;undo日志是數(shù)據(jù)落盤后寫COMMIT日志棚菊;redo日志是數(shù)據(jù)落盤前先寫COMMIT日志。
2.2 redo日志規(guī)則
在redo日志中< T,X,v >表示:事物T將數(shù)據(jù)庫元素X改為新值v叔汁。
- redo log規(guī)則:R1:在修改磁盤上的任何數(shù)據(jù)庫元素X以前统求,要保證與X的這一修改相關(guān)的所有的日志記錄,包括更新記錄< T,X,v >及< COMMIT >記錄攻柠,都必須出現(xiàn)在磁盤上球订。
因此當(dāng)使用redo日志時,與一個事務(wù)相關(guān)的材料寫到磁盤的順序為:
- 指出被修改元素的日志記錄
- 寫COMMIT日志
- 修改數(shù)據(jù)庫元素自身
簡單描述刷盤順序就是:改動日志->COMMIT日志->數(shù)據(jù)庫元素的改動
2.3 使用redo日志進行恢復(fù)
根據(jù)R1規(guī)則瑰钮,如果日志中沒有< COMMIT T >冒滩,說明事物T的改動都沒有落盤,因此我么可以什么都不做浪谴。如果日志中有< COMMIT T >开睡,數(shù)據(jù)改動是否全部落盤無法確定因苹。
redo log恢復(fù)步驟:
- 從首部向下開始掃描日志(這個順序是為了恢復(fù)到最后的一致狀態(tài)),記錄所有< T,X,v >篇恒。(因為需要重做扶檐,所以必須從首部向下掃描)
- 如果T是未提交的,則什么也不做胁艰。
- 如果T是已提交的款筑,則將數(shù)據(jù)庫元素X重寫為v。
- 最后腾么,為所有未提交的事物寫一個< ABORT T >記錄并刷新日志奈梳。
簡而言之,從首部向下解虱,忽略未提交事物攘须,重做已提交事物。
2.4 redo log的checkpoint
- 寫日志記錄<START CKPT(T1, T2, ..., Tk)>殴泰,其中Ti表示當(dāng)前活躍事務(wù)于宙,并刷新日志。
- 當(dāng)日志記錄<START CKPT>寫入日志后悍汛,把所有已提交事務(wù)在緩沖區(qū)的新值寫到磁盤上去捞魁。
- 寫日志記錄<END CKPT>并刷新日志。
舉例:在做檢查點的過程中需要將之前已提交事物T1的改動刷新到磁盤员凝。
<START T1>
<T1,A,5>
<START T2>
<COMMIT T1>
<T2,B,10>
<START CKPT(T2)>
<T2,C,15>
<START T3>
<T3,D,20>
<END CKPT>
<COMMIT T2>
<COMMIT T3>
2.5 使用帶檢查點的redo日志的恢復(fù)
下面說一下如何重放帶檢查點的redo日志:
1)如果最后一條檢查點記錄是< END CKPT >
a. < START CKPT(t1,...署驻,Tk) >之前提交的事物其修改已落盤,無需恢復(fù)健霹。
b. < START CKPT(t1,...旺上,Tk) >中的或之后啟動的事物,即使已經(jīng)提交糖埋,其修改都可能未落盤宣吱,需要redo。
2)如果最后一條檢查點記錄是< START CKPT >
不能確定這之前提交事物的修改是否已經(jīng)全部落盤瞳别。需要找到前一個< END CKPT >和與之對應(yīng)的< START CKPT(S1,...,Sm) >征候,重做S1,...,Sm中和< START CKPT(S1,...,Sm) >之后啟動的事物中所有已經(jīng)提交的事物(也就是說再匹配1))。
3 undo/redo log
3.1 undo log和redo log的缺陷
undo log 要求數(shù)據(jù)在事物結(jié)束后立即寫到磁盤祟敛,這會增加磁盤I/O疤坝。
redo log 要求我們在事物提交和日志記錄刷新以前,將所有修改過的塊保留在緩沖區(qū)中馆铁,這會增加事物需要的平均緩沖區(qū)數(shù)跑揉。
如果數(shù)據(jù)庫元素不是完整的塊或塊塊集,在檢測點處理過程中,Undo日志和Redo日志在如何處理緩沖區(qū)上存在矛盾历谍。而undo/redo log可以很好的解決這些問題现拒,通過同時記錄新舊值,提供了動作順序上的更大靈活性望侈。
3.2 undo/redo log
日志記錄< T,X,v,w >:事物T改變了數(shù)據(jù)庫元素X印蔬,由v改為w。
規(guī)則:
- UR1:在由于某個事務(wù)T所做改變而修改磁盤上的數(shù)據(jù)庫元素X前脱衙,更新記錄 < T, X, v, w > 必須出現(xiàn)在磁盤上侥猬。
也就是說,在修改數(shù)據(jù)庫元素前,必須先寫事務(wù)更新日志岂丘,< COMMIT T >記錄可先也可后于數(shù)據(jù)本身落盤陵究。 - UR2: < COMMIT T >記錄一旦出現(xiàn)在日志中,就必須被刷新到磁盤上< FLUSH LOG >奥帘。
undo/redo log 也被稱作write ahead log。當(dāng)使用 undo/redo 日志時仪召,與一個事務(wù)相關(guān)的材料寫到磁盤的順序為:
- 記錄update日志
- 更新數(shù)據(jù)庫(不一定持久化寨蹋,寫入緩存中)
- 在合適的時候?qū)慶ommit日志 (在磁盤上任何數(shù)據(jù)庫元素的修改之前或之后,即第3步可能比第2步可能早扔茅,或者可能晚)
3.3 重放undo/redo log
重放策略:
- 從前往后遍歷日志已旧,redo所有已提交事物。
- 從后往前遍歷日志召娜,undo所有未提交事物运褪,并追加< ABORT T >。
3.4 undo/redo log的checkpoint
步驟:
- 寫入日志記錄< START CKPT(T1,...,Tk) >,其中T1,...,Tk是所有當(dāng)前活躍事物玖瘸,并刷新日志秸讹。
- 將所有緩沖區(qū)中的數(shù)據(jù)刷盤(包括未提交的事物修改)。
- 寫入日志記錄< END CKPT >雅倒,并刷新日志璃诀。
對于2) 需要注意,我們可以容忍將未提交事物寫入的數(shù)據(jù)落盤蔑匣,所以我們能夠容忍小于完整塊的數(shù)據(jù)庫元素劣欢,并因此共享緩沖區(qū)。
唯一要求是:事物在不確定其不會中止之前裁良,不能寫入任何值(甚至連寫到主存緩沖區(qū)也不允許)凿将。
事務(wù)恢復(fù)中的奇怪行為
讀者可能注意到,我們并沒有指明在使用 undo/redo 日志恢復(fù)時是先撤銷還是先重做价脾。事實上牧抵,不管是先撤銷還是先重做,我們都會面臨如下情況:提交并被重做的事務(wù)T讀取值X彼棍,該值是由某個未提交并被撤銷的事務(wù)U寫入的灭忠。問題不在于我們是先重做(使X具有U以前的值)膳算;還是先撤銷(使X具有由T寫入的值)。不管哪種方式弛作,這種情況都沒有意義涕蜂,因為數(shù)據(jù)庫的最終狀態(tài)不對應(yīng)于任何原子的事務(wù)序列的結(jié)果。這是由數(shù)據(jù)庫選擇的事務(wù)隔離級別來決定的映琳。
四机隙、對介質(zhì)故障的防護
系統(tǒng)故障時磁盤上的數(shù)據(jù)不會丟失,而主存中的臨時數(shù)據(jù)會丟失萨西。如果以下條件成立有鹿,日志系統(tǒng)可以幫助我們恢復(fù)系統(tǒng)故障。
a. 日志所在的磁盤不同于存放數(shù)據(jù)的磁盤谎脯。
b. 日志在檢查點以后永遠不會被丟棄葱跋。
c. 日志是redo或undo/redo類型,因為新值被存儲在日志中源梭。
備份
如果有可能暫時關(guān)閉數(shù)據(jù)庫娱俺,我們可以采用一種備份(archive)的方法,再另外的介質(zhì)上創(chuàng)建一個備份拷貝废麻,并將它們存放在安全的地方荠卷。當(dāng)數(shù)據(jù)庫介質(zhì)故障時,就可以恢復(fù)到該時刻的狀態(tài)烛愧。
如果從備份以來的日志都有得到保存油宜,我們可以使用數(shù)據(jù)庫備份+日志,將數(shù)據(jù)庫恢復(fù)到一個更新的狀態(tài)怜姿。
當(dāng)數(shù)據(jù)庫規(guī)模很大時建立完全備份不太現(xiàn)實慎冤。因此,數(shù)據(jù)庫備份通常分兩個級別:
a. 完全轉(zhuǎn)儲社牲,這時需要拷貝整個數(shù)據(jù)庫粪薛。也叫做0級備份。
b. 增量轉(zhuǎn)儲搏恤,這時只需拷貝上一次完全轉(zhuǎn)儲或增量轉(zhuǎn)儲之后改變的數(shù)據(jù)庫元素违寿。增量轉(zhuǎn)儲可以有多次,根據(jù)次數(shù)被稱為i級備份熟空。
我們可以用完全轉(zhuǎn)儲 + n次增量轉(zhuǎn)儲 + redo或undo/redo日志的方式將數(shù)據(jù)庫恢復(fù)到最新的狀態(tài)藤巢。
非靜止轉(zhuǎn)儲
為防止拷貝的數(shù)據(jù)庫元素只有部分被改變,完全或增量轉(zhuǎn)儲都要求數(shù)據(jù)庫暫時停機息罗。非靜止檢查點試圖在磁盤上建立數(shù)據(jù)庫在檢查點開始時狀態(tài)的一個拷貝掂咒,我們可以依賴于檢查點附近一段時間內(nèi)的很小一部分日志,彌補和該狀態(tài)之間的任何偏差。類似地绍刮,非靜止轉(zhuǎn)儲試圖建立轉(zhuǎn)儲開始時數(shù)據(jù)庫的一個拷貝温圆,轉(zhuǎn)儲過程中幾分鐘甚至幾個小時內(nèi)的數(shù)據(jù)庫元素變化可以通過轉(zhuǎn)儲過程中的日志來整理數(shù)據(jù),使數(shù)據(jù)庫達到一個新的一致狀態(tài)孩革。
非靜止轉(zhuǎn)儲按某種固定的順序拷貝數(shù)據(jù)庫元素岁歉,有可能正好在這些元素被執(zhí)行中的事務(wù)改變時。其結(jié)果是膝蜈,拷貝到備份中的數(shù)據(jù)庫元素可能是也可能不是轉(zhuǎn)儲開始時的值锅移。只要在轉(zhuǎn)儲持續(xù)過程中的日志得到保留,這樣的差異可以通過日志來糾正饱搏。
五非剃、參考
- 數(shù)據(jù)庫系統(tǒng)實現(xiàn)
- http://blog.csdn.net/ggxxkkll/article/details/7616739