是不是我们的数据库,加上一套成熟可靠的备份软件(比如NBU、DP、TSM等),以及购置了可靠的大容量的带库就足够了?或者下面一个案例能够给我们一些启示。

案例来自于一个老客户,一套重要系统的Oracle RAC数据库,由于硬件问题,一个包含关键业务数据的文件被离线(在归档模式下,写文件出错会导致文件被置为离线状态,而不是库宕掉)。在尝试recover datafile的时候,提示缺少一个归档日志。归档日志已经被备到带库上,本地磁盘上已经没有了这个归档日志文件。

这套库是用TSM备份的,使用rman还原归档日志,称找不到这个归档日志。看起来出问题了,在rman中用下面的命令:

list backup of archivelog sequence 18884 thread 2;

返回的结果说没有找到这个归档日志的备份。甚至于用命令:

list backup of archivelog all;

发现好些归档日志没有了备份。但是这些文件又不在本地磁盘上。那么,这里有几种可能:

  1. 归档日志被人为地删除,根本没有备份
  2. 归档日志的备份已经被删除,通过delete backup命令

第1种情况,可以从v$archived_log视图判断归档日志到底有没有备份(通过BACKUP_COUNT列)。我们可以从备份保留的日志中判断第2种情况是否存在。

检查备份操作的日志,发现恢复所需要的归档日志文件是成功备份了的。那备份怎么消失了?在备份操作的日志目录中,还发现一个日志文件有crosscheck backup然后delete expired backup的记录,而被删除的备份正好有恢复所需要的归档日志所在的备份。所以,这里可以知道,出现了上述说的第2种情况,备份被删除了。

为什么会出现备份在crosscheck backup之后成为expired状态,这个结果就来源于在rman中进行crosscheck backup时,备份服务器返回的结果表明这个备份不可访问了,或许是权限问题,或者是配置不当,或者是备份文件真的不能访问了。从目前的情况来看,备份都是成功的,看上去带库、备份服务器都是好的。不过这里值得注意的是,这是一套RAC数据库,归档日志是在节点1上完成的,在节点1上也进行了crosscheck backup,并且是先进行crosscheck,而其结果表明备份是available状态的。但是随后节点2的crosscheck的结果是expired,那只能说明由于权限或配置问题,导致节点2不能访问到节点1所做的备份(当然不排除在这个时间窗口内备份在带库上或备份服务端删除的可能,但是可能性较小,所以分析问题得先从可能性更大的入手)。

是不是没救了?答案在于,备份到底还在不在带库上?

节点1先crosscheck正常,随后节点2 crosscheck称备份文件没有或不可访问,然后节点2删除了备份。只不过这里要注意的是:既然crosscheck不能访问不到备份,那么delete操作也应当不会真正删除备份(备份都访问不到怎么能物理删除呢?),只是把备份信息从catalog里面删除掉而已。所以这里的结论是真正的备份还在带库上。可以找备份管理员或通过TSM命令来检查,不过客户说,搞TSM的人找不到了。

接下来,尝试找找看,有没有在备份归档日志之后,但在删除备份之前的备份控制文件存在。可惜没有,如果有,可以用这个控制文件来还原归档日志。
或许可以通过手工在catalog库里面添加记录,然后同步到控制文件来进行恢复。
不过我们还有另一个方法,就是直接使用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; 

幸运的是,归档日志成功还原,然后数据文件成功recover。

从这个案例中,我们获得的是:

  • 并不是说,备份没有报错,备份正常运行就足够了。在备份的时候,为了避免备份出错而失败,在备份之前进行crosscheck archivelog,把人为删除掉的归档从catalog中去掉从而不备份,也就在备份时不报错;或者是备份时skip inaccessible;实际上这有点类似于掩耳盗铃,备份可能是残缺的,根本不可用。
  • rman中的crosscheck backup,使得backup成为expired状态,这本身说明可能存在问题,而不仅仅是从catalog中删除备份了事。针对这个案例来说,backup成为expired,本身就是一种异常,就应该要去检查备份服务器的配置等。
  • 所有涉及备份相关的操作,包括备份,删除备份,crosscheck备份,保留详细的rman日志是非常有用的。
  • 应该在每次备份后,对控制文件进行一次备份;打开控制文件的AUTO BACKUP也是有必要的。

--The End.