數(shù)據(jù)恢復(fù):僅僅只做備份是不夠的
是不是我們的數(shù)據(jù)庫(kù),加上一套成熟可靠的備份軟件(比如NBU、DP、TSM等),以及購(gòu)置了可靠的大容量的帶庫(kù)就足夠了?或者下面一個(gè)案例能夠給我們一些啟示。
案例來(lái)自于一個(gè)老客戶,一套重要系統(tǒng)的Oracle RAC數(shù)據(jù)庫(kù),由于硬件問(wèn)題,一個(gè)包含關(guān)鍵業(yè)務(wù)數(shù)據(jù)的文件被離線(在歸檔模式下,寫文件出錯(cuò)會(huì)導(dǎo)致文件被置為離線狀態(tài),而不是庫(kù)宕掉)。在嘗試recover datafile的時(shí)候,提示缺少一個(gè)歸檔日志。歸檔日志已經(jīng)被備到帶庫(kù)上,本地磁盤上已經(jīng)沒有了這個(gè)歸檔日志文件。
這套庫(kù)是用TSM備份的,使用rman還原歸檔日志,稱找不到這個(gè)歸檔日志。看起來(lái)出問(wèn)題了,在rman中用下面的命令:
list backup of archivelog sequence 18884 thread 2;
返回的結(jié)果說(shuō)沒有找到這個(gè)歸檔日志的備份。甚至于用命令:
list backup of archivelog all;
發(fā)現(xiàn)好些歸檔日志沒有了備份。但是這些文件又不在本地磁盤上。那么,這里有幾種可能:
- 歸檔日志被人為地刪除,根本沒有備份
- 歸檔日志的備份已經(jīng)被刪除,通過(guò)delete backup命令
第1種情況,可以從v$archived_log視圖判斷歸檔日志到底有沒有備份(通過(guò)BACKUP_COUNT列)。我們可以從備份保留的日志中判斷第2種情況是否存在。
檢查備份操作的日志,發(fā)現(xiàn)恢復(fù)所需要的歸檔日志文件是成功備份了的。那備份怎么消失了?在備份操作的日志目錄中,還發(fā)現(xiàn)一個(gè)日志文件有crosscheck backup然后delete expired backup的記錄,而被刪除的備份正好有恢復(fù)所需要的歸檔日志所在的備份。所以,這里可以知道,出現(xiàn)了上述說(shuō)的第2種情況,備份被刪除了。
為什么會(huì)出現(xiàn)備份在crosscheck backup之后成為expired狀態(tài),這個(gè)結(jié)果就來(lái)源于在rman中進(jìn)行crosscheck backup時(shí),備份服務(wù)器返回的結(jié)果表明這個(gè)備份不可訪問(wèn)了,或許是權(quán)限問(wèn)題,或者是配置不當(dāng),或者是備份文件真的不能訪問(wèn)了。從目前的情況來(lái)看,備份都是成功的,看上去帶庫(kù)、備份服務(wù)器都是好的。不過(guò)這里值得注意的是,這是一套R(shí)AC數(shù)據(jù)庫(kù),歸檔日志是在節(jié)點(diǎn)1上完成的,在節(jié)點(diǎn)1上也進(jìn)行了crosscheck backup,并且是先進(jìn)行crosscheck,而其結(jié)果表明備份是available狀態(tài)的。但是隨后節(jié)點(diǎn)2的crosscheck的結(jié)果是expired,那只能說(shuō)明由于權(quán)限或配置問(wèn)題,導(dǎo)致節(jié)點(diǎn)2不能訪問(wèn)到節(jié)點(diǎn)1所做的備份(當(dāng)然不排除在這個(gè)時(shí)間窗口內(nèi)備份在帶庫(kù)上或備份服務(wù)端刪除的可能,但是可能性較小,所以分析問(wèn)題得先從可能性更大的入手)。
是不是沒救了?答案在于,備份到底還在不在帶庫(kù)上?
節(jié)點(diǎn)1先crosscheck正常,隨后節(jié)點(diǎn)2 crosscheck稱備份文件沒有或不可訪問(wèn),然后節(jié)點(diǎn)2刪除了備份。只不過(guò)這里要注意的是:既然crosscheck不能訪問(wèn)不到備份,那么delete操作也應(yīng)當(dāng)不會(huì)真正刪除備份(備份都訪問(wèn)不到怎么能物理刪除呢?),只是把備份信息從catalog里面刪除掉而已。所以這里的結(jié)論是真正的備份還在帶庫(kù)上。可以找備份管理員或通過(guò)TSM命令來(lái)檢查,不過(guò)客戶說(shuō),搞TSM的人找不到了。
接下來(lái),嘗試找找看,有沒有在備份歸檔日志之后,但在刪除備份之前的備份控制文件存在。可惜沒有,如果有,可以用這個(gè)控制文件來(lái)還原歸檔日志。
或許可以通過(guò)手工在catalog庫(kù)里面添加記錄,然后同步到控制文件來(lái)進(jìn)行恢復(fù)。
不過(guò)我們還有另一個(gè)方法,就是直接使用dbms_backup_restore包:
- DECLARE
- v_dev varchar2(50);
- v_done boolean:=false;
- BEGIN
- v_dev:=sys.dbms_backup_restore.deviceAllocate(type=>'sbt_tape',ident=>'t1',params=>'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)');
- dbms_backup_restore.RestoreSetArchivedLog(destination=>'/arch');
- dbms_backup_restore.RestoreArchivedLog(thread=>2,sequence=>18884);
- dbms_backup_restore.RestoreBackupPiece(done => v_done,handle => 'xxx_archlog_backup<xxxx1_7941 :796937510>.dbf', params => null);
- sys.dbms_backup_restore.deviceDeallocate;
- END;
幸運(yùn)的是,歸檔日志成功還原,然后數(shù)據(jù)文件成功recover。
從這個(gè)案例中,我們獲得的是:
- 并不是說(shuō),備份沒有報(bào)錯(cuò),備份正常運(yùn)行就足夠了。在備份的時(shí)候,為了避免備份出錯(cuò)而失敗,在備份之前進(jìn)行crosscheck archivelog,把人為刪除掉的歸檔從catalog中去掉從而不備份,也就在備份時(shí)不報(bào)錯(cuò);或者是備份時(shí)skip inaccessible;實(shí)際上這有點(diǎn)類似于掩耳盜鈴,備份可能是殘缺的,根本不可用。
- rman中的crosscheck backup,使得backup成為expired狀態(tài),這本身說(shuō)明可能存在問(wèn)題,而不僅僅是從catalog中刪除備份了事。針對(duì)這個(gè)案例來(lái)說(shuō),backup成為expired,本身就是一種異常,就應(yīng)該要去檢查備份服務(wù)器的配置等。
- 所有涉及備份相關(guān)的操作,包括備份,刪除備份,crosscheck備份,保留詳細(xì)的rman日志是非常有用的。
- 應(yīng)該在每次備份后,對(duì)控制文件進(jìn)行一次備份;打開控制文件的AUTO BACKUP也是有必要的。


























