汪 洋
(安慶師范大學(xué)計(jì)算機(jī)與信息學(xué)院,安徽安慶246133)
數(shù)據(jù)庫(kù)系統(tǒng)發(fā)生故障不可避免,如何保證發(fā)生故障后迅速將數(shù)據(jù)庫(kù)恢復(fù)到正確的狀態(tài),是衡量一個(gè)數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS)優(yōu)劣的重要指標(biāo)[1],也是數(shù)據(jù)庫(kù)管理員(DBA)必備的技能之一。深刻理解并掌握數(shù)據(jù)庫(kù)系統(tǒng)恢復(fù)策略是數(shù)據(jù)庫(kù)教學(xué)中的一個(gè)重點(diǎn)和難點(diǎn),現(xiàn)有數(shù)據(jù)庫(kù)教材及實(shí)際教學(xué)中對(duì)恢復(fù)策略的介紹太偏重理論,學(xué)生理解困難,難以真正掌握其實(shí)際應(yīng)用。本文以案例形式詳細(xì)分析了事務(wù)故障、系統(tǒng)故障和介質(zhì)故障[1-3]這3類數(shù)據(jù)庫(kù)故障的成因和產(chǎn)生的結(jié)果,并詳細(xì)介紹了恢復(fù)策略。
事務(wù)故障是對(duì)單個(gè)事務(wù)而言的,指發(fā)生事務(wù)故障時(shí),該事務(wù)未運(yùn)行到Commit Transaction 或Rollback Transaction處被終止,此時(shí)該未完成的事務(wù)把對(duì)數(shù)據(jù)庫(kù)的修改已寫入數(shù)據(jù)庫(kù)。
案例1如圖1所示,T1事務(wù)由兩個(gè)操作構(gòu)成,A=A+1,B=B-1。T1事務(wù)在運(yùn)行完第一個(gè)操作A=A+1后,發(fā)生了事務(wù)故障,第二個(gè)操作B=B-1沒有做,顯然T1事務(wù)是一個(gè)未完成的事務(wù)。若A的初值為1,B的初值為2,在如圖2所示的數(shù)據(jù)庫(kù)存儲(chǔ)中,此時(shí)事務(wù)T1對(duì)A的修改操作已寫入數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)中A的值由1被修改為2,很顯然數(shù)據(jù)庫(kù)中A=2是錯(cuò)誤的,此時(shí)數(shù)據(jù)庫(kù)處于不一致(不正確)的狀態(tài),其原因就在于未完成的T1事務(wù)對(duì)A的修改操作已經(jīng)寫入到數(shù)據(jù)庫(kù)。
對(duì)于事務(wù)故障的恢復(fù)策略是利用日志文件對(duì)未完成的事務(wù)執(zhí)行撤消處理(Undo)。DBMS將事務(wù)的開始標(biāo)記、結(jié)束標(biāo)記和事務(wù)對(duì)數(shù)據(jù)庫(kù)的所有更新操作形成日志記錄并寫入日志文件,在案例1中形成了如圖3所示的日志文件。
恢復(fù)策略:(1)反向掃描圖3所示的文件日志,查找T1事務(wù)的更新操作;(2)對(duì)T1事務(wù)的每一個(gè)更新操作執(zhí)行逆操作,將圖3中日志記錄中更新前的值A(chǔ)=1寫入數(shù)據(jù)庫(kù),此時(shí)圖2中數(shù)據(jù)庫(kù)中A的值由2又變回原值1;(3)繼續(xù)反向掃描日志文件,查找T1事務(wù)的其他更新操作,并做同樣處理,直至讀到T1事務(wù)的開始標(biāo)記結(jié)束。

圖1 案例1事務(wù)故障示意圖

圖2 案例1數(shù)據(jù)庫(kù)存儲(chǔ)變化示意圖

圖3 案例1的日志文件
系統(tǒng)故障是指由于某些原因?qū)е聰?shù)據(jù)庫(kù)系統(tǒng)必須重啟的故障[1]。發(fā)生系統(tǒng)故障時(shí),數(shù)據(jù)庫(kù)中有多個(gè)事務(wù)發(fā)生事務(wù)故障,此時(shí),未完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改已寫入數(shù)據(jù)庫(kù),而已完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改可能放于緩沖區(qū)內(nèi)還未寫入數(shù)據(jù)庫(kù)。以簡(jiǎn)單易懂為目的,我們以兩個(gè)事務(wù)為例來(lái)介紹系統(tǒng)故障的成因和結(jié)果。
案例2如圖4所示,當(dāng)前數(shù)據(jù)庫(kù)系統(tǒng)中運(yùn)行T1和T2兩個(gè)事務(wù),圖5所示的數(shù)據(jù)庫(kù)存儲(chǔ)中A、B、C、D的初值分別為1,2,3,4。T1事務(wù)執(zhí)行完第一個(gè)操作A=A+1,并把對(duì)A值的修改寫入數(shù)據(jù)庫(kù),此時(shí)數(shù)據(jù)庫(kù)內(nèi)A的值由1變?yōu)?。然后T2事務(wù)依次執(zhí)行了C=C+2,D=D-2兩個(gè)操作,此時(shí)修改值C=5,D=2存放于如圖6所示的系統(tǒng)緩沖區(qū)中,還未寫入數(shù)據(jù)庫(kù)時(shí)就發(fā)生了系統(tǒng)故障。顯然數(shù)據(jù)庫(kù)中A=2是錯(cuò)誤的,此時(shí)數(shù)據(jù)庫(kù)處于不一致(不正確)的狀態(tài),其原因是未完成的T1 事務(wù)對(duì)A 的修改操作已經(jīng)寫入到數(shù)據(jù)庫(kù);另一方面,T2是已完成事務(wù),但對(duì)C和D值的修改沒有來(lái)得及寫入數(shù)據(jù)庫(kù)中。
發(fā)生系統(tǒng)故障時(shí),未完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)的更新操作已寫入數(shù)據(jù)庫(kù),已完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)的更新留在緩沖區(qū)中未寫入數(shù)據(jù)庫(kù)。系統(tǒng)故障的恢復(fù)策略是利用日志文件形成兩個(gè)隊(duì)列:Undo隊(duì)列和Redo隊(duì)列。對(duì)Undo 隊(duì)列中的未完成事務(wù)執(zhí)行撤消處理(Undo),對(duì)Redo 隊(duì)列中的已完成事務(wù)執(zhí)行重做處理(Redo)。在案例2中形成了如圖7所示的日志文件。
恢復(fù)策略:(1)正向掃描圖7 所示的日志文件,未完成事務(wù)T1 放入U(xiǎn)ndo 對(duì)列,已完成事務(wù)T2 放入Redo隊(duì)列。(2)對(duì)Undo隊(duì)列中所有事務(wù)逐個(gè)執(zhí)行事務(wù)故障恢復(fù)策略,即進(jìn)行Undo處理。反向掃描如圖7所示的日志文件,對(duì)T1事務(wù)的更新操作執(zhí)行逆操作,即將日志記錄中更新前的值A(chǔ)=1寫入數(shù)據(jù)庫(kù),此時(shí)圖6中數(shù)據(jù)庫(kù)中A的值由2又為回原值1。(3)對(duì)Redo隊(duì)列所有事務(wù)逐個(gè)進(jìn)行Redo處理。正向掃描如圖7所示的日志文件,對(duì)T2事務(wù)的所有更新操作執(zhí)行重新登記,即將日志記錄中更新后的值C=5,D=2寫入數(shù)據(jù)庫(kù)。

圖4 案例2系統(tǒng)故障示意圖

圖5 案例2數(shù)據(jù)庫(kù)存儲(chǔ)變化示意圖

圖6 案例2緩沖區(qū)示意圖

圖7 案例2的日志文件
介質(zhì)故障是指由于某些原因?qū)е麓娣旁诖鎯?chǔ)設(shè)備上數(shù)據(jù)庫(kù)部分或全部遭到破壞,磁盤上的物理數(shù)據(jù)和日志文件部分或全部丟失[3]。介質(zhì)故障的恢復(fù)需要后備副本和日志文件副本,DBA在數(shù)據(jù)庫(kù)的日常運(yùn)行維護(hù)中要制定詳細(xì)的備份計(jì)劃并做好備份工作。限于文章篇幅,本文以SQL Server 為具體DBMS[4],通過(guò)一個(gè)實(shí)際案例簡(jiǎn)要介紹數(shù)據(jù)庫(kù)備份和介質(zhì)故障恢復(fù)策略。
案例3如圖8所示,現(xiàn)有一個(gè)產(chǎn)品銷售數(shù)據(jù)庫(kù)cpxs,其中有產(chǎn)品表CP、產(chǎn)品銷售表CPXSB、銷售商表XSS 3張表。首先創(chuàng)建一個(gè)備份設(shè)備Test1,接著將整個(gè)cpxs數(shù)據(jù)庫(kù)進(jìn)行完全備份并存放于Test1備份設(shè)備上,形成FILE1文件;然后向數(shù)據(jù)庫(kù)中添加人事表RS,并進(jìn)行一次差異備份并存放于Test1備份設(shè)備上,形成FILE2文件;最后向數(shù)據(jù)庫(kù)中添加訂貨表DHB,并進(jìn)行一次日志備份,并存放于Test1備份設(shè)備上,形成FILE3文件。

圖8 案例3備份過(guò)程示意圖
該cpxs數(shù)據(jù)庫(kù)備份過(guò)程的詳細(xì)T-SQL語(yǔ)句如下:
sp_addumpdevice'disk','Test1','D:ackupTest1.bak'/*增加Test1備份設(shè)備*/
BACKUP DATABASE cpxs TO Test1 WITH INIT/*重寫完全備份cpxs到Test1備份設(shè)備,NOINIT為追加*/
create table RS/*添加員工人事表RS*/
(emp_no char(5)primary key,emp_name varchar(10), sex char(2),dept varchar(10))
BACKUP DATABASE cpxs TO Test1 WITH DIFFERENTIAL/*追加差異備份cpxs到Test1備份設(shè)備*/
create table DHB/*添加訂貨表DHB*/
(order_no char(5),prod_no char(5),qty int price numeric(7,2),order_date datetime)
BACKUP LOG cpxs TO Test1/*追加備份日志文件到Test1備份設(shè)備*/
介質(zhì)故障的恢復(fù)需要DBA重裝備份的數(shù)據(jù)庫(kù)副本和有關(guān)的日志文件副本,并執(zhí)行系統(tǒng)提供的恢復(fù)命令。
恢復(fù)策略:經(jīng)過(guò)前期備份后,形成了兩個(gè)數(shù)據(jù)庫(kù)副本和一個(gè)日志副本,分別對(duì)應(yīng)存儲(chǔ)于Test1備份設(shè)備的FILE1、FILE2和FILE3。DBA重裝這些數(shù)據(jù)庫(kù)副本和日志副本可以得到不同狀態(tài)的cpxs數(shù)據(jù)庫(kù),解決介質(zhì)故障破壞磁盤上數(shù)據(jù)庫(kù)的問題。該cpxs數(shù)據(jù)庫(kù)恢復(fù)過(guò)程的詳細(xì)T-SQL語(yǔ)句如下:
ALTER DATABASE cpxs SET RECOVERY FULL/*設(shè)置cpxs數(shù)據(jù)庫(kù)恢復(fù)模型為全模型*/
RESTORE DATABASE cpxs FROM Test1 WITH FILE=1, NORECOVERY/*恢復(fù)完整備份,完全備份是Test1備份設(shè)備的FILE1,并掛起數(shù)據(jù)庫(kù)cpxs*/
RESTORE DATABASE cpxs FROM Test1 WITH FILE=2, NORECOVERY/*恢復(fù)差異備份,差異備份是Test1備份設(shè)備的FILE2,并掛起數(shù)據(jù)庫(kù)cpxs*/
RESTORE LOG cpxs FROM Test1 WITH FILE=3, RECOVERY/*恢復(fù)日志備份,日志備份是Test1備份設(shè)備的FILE3*/
為解決數(shù)據(jù)庫(kù)恢復(fù)教學(xué)中理論過(guò)于抽象、學(xué)生不易掌握的問題,作者在多年數(shù)據(jù)庫(kù)教學(xué)實(shí)踐研究中,探索出一種基于案例的數(shù)據(jù)庫(kù)恢復(fù)策略教學(xué)方法,該方法直觀易懂、簡(jiǎn)單清晰、操作性強(qiáng),學(xué)生參與度高,易為學(xué)生理解和掌握。該方法在多年的教學(xué)實(shí)踐中得到了檢驗(yàn),并取得了較好的教學(xué)效果。
安慶師范大學(xué)學(xué)報(bào)(自然科學(xué)版)2019年4期