數(shù)據(jù)恢復(fù):僅僅只做備份是不夠的
是不是我們的數(shù)據(jù)庫,加上一套成熟可靠的備份軟件(比如NBU、DP、TSM等),以及購置了可靠的大容量的帶庫就足夠了?或者下面一個(gè)案例能夠給我們一些啟示。
案例來自于一個(gè)老客戶,一套重要系統(tǒng)的Oracle RAC數(shù)據(jù)庫,由于硬件問題,一個(gè)包含關(guān)鍵業(yè)務(wù)數(shù)據(jù)的文件被離線(在歸檔模式下,寫文件出錯(cuò)會導(dǎo)致文件被置為離線狀態(tài),而不是庫宕掉)。在嘗試recover datafile的時(shí)候,提示缺少一個(gè)歸檔日志。歸檔日志已經(jīng)被備到帶庫上,本地磁盤上已經(jīng)沒有了這個(gè)歸檔日志文件。
這套庫是用TSM備份的,使用rman還原歸檔日志,稱找不到這個(gè)歸檔日志??雌饋沓鰡栴}了,在rman中用下面的命令:
list backup of archivelog sequence 18884 thread 2;
返回的結(jié)果說沒有找到這個(gè)歸檔日志的備份。甚至于用命令:
list backup of archivelog all;
發(fā)現(xiàn)好些歸檔日志沒有了備份。但是這些文件又不在本地磁盤上。那么,這里有幾種可能:
- 歸檔日志被人為地刪除,根本沒有備份
- 歸檔日志的備份已經(jīng)被刪除,通過delete backup命令
第1種情況,可以從v$archived_log視圖判斷歸檔日志到底有沒有備份(通過BACKUP_COUNT列)。我們可以從備份保留的日志中判斷第2種情況是否存在。
檢查備份操作的日志,發(fā)現(xiàn)恢復(fù)所需要的歸檔日志文件是成功備份了的。那備份怎么消失了?在備份操作的日志目錄中,還發(fā)現(xiàn)一個(gè)日志文件有crosscheck backup然后delete expired backup的記錄,而被刪除的備份正好有恢復(fù)所需要的歸檔日志所在的備份。所以,這里可以知道,出現(xiàn)了上述說的第2種情況,備份被刪除了。
為什么會出現(xiàn)備份在crosscheck backup之后成為expired狀態(tài),這個(gè)結(jié)果就來源于在rman中進(jìn)行crosscheck backup時(shí),備份服務(wù)器返回的結(jié)果表明這個(gè)備份不可訪問了,或許是權(quán)限問題,或者是配置不當(dāng),或者是備份文件真的不能訪問了。從目前的情況來看,備份都是成功的,看上去帶庫、備份服務(wù)器都是好的。不過這里值得注意的是,這是一套RAC數(shù)據(jù)庫,歸檔日志是在節(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,那只能說明由于權(quán)限或配置問題,導(dǎo)致節(jié)點(diǎn)2不能訪問到節(jié)點(diǎn)1所做的備份(當(dāng)然不排除在這個(gè)時(shí)間窗口內(nèi)備份在帶庫上或備份服務(wù)端刪除的可能,但是可能性較小,所以分析問題得先從可能性更大的入手)。
是不是沒救了?答案在于,備份到底還在不在帶庫上?
節(jié)點(diǎn)1先crosscheck正常,隨后節(jié)點(diǎn)2 crosscheck稱備份文件沒有或不可訪問,然后節(jié)點(diǎn)2刪除了備份。只不過這里要注意的是:既然crosscheck不能訪問不到備份,那么delete操作也應(yīng)當(dāng)不會真正刪除備份(備份都訪問不到怎么能物理刪除呢?),只是把備份信息從catalog里面刪除掉而已。所以這里的結(jié)論是真正的備份還在帶庫上??梢哉覀浞莨芾韱T或通過TSM命令來檢查,不過客戶說,搞TSM的人找不到了。
接下來,嘗試找找看,有沒有在備份歸檔日志之后,但在刪除備份之前的備份控制文件存在??上]有,如果有,可以用這個(gè)控制文件來還原歸檔日志。
或許可以通過手工在catalog庫里面添加記錄,然后同步到控制文件來進(jìn)行恢復(fù)。
不過我們還有另一個(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è)案例中,我們獲得的是:
- 并不是說,備份沒有報(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),這本身說明可能存在問題,而不僅僅是從catalog中刪除備份了事。針對這個(gè)案例來說,backup成為expired,本身就是一種異常,就應(yīng)該要去檢查備份服務(wù)器的配置等。
- 所有涉及備份相關(guān)的操作,包括備份,刪除備份,crosscheck備份,保留詳細(xì)的rman日志是非常有用的。
- 應(yīng)該在每次備份后,對控制文件進(jìn)行一次備份;打開控制文件的AUTO BACKUP也是有必要的。