Redo故障的恢复:
我们已经知道日志文件对于数据库来说非常重要,在实际使用过程中,可以会遇到各种各样的问题,接下来将介绍一些在日常数据库维护中经常会遇到的情况。
1. 丢失非活动日志组的故障恢复:
如果数据库丢失的是非活动(INACTIVE)日志组,由于非活动日志组已经完成检查点,数据库不会发生数据损失,此时只需要通过Clear重建该日志组即可恢复。
⑴ 首先删除一个非活动日志组,模拟一次故障损失:
sys@TQGZS> ! mv /u01/oracle/oradata/tqgzs/redo02.log /u01/oracle/databak/
⑵ 如果数据库日志切换,使用到该日志组,则数据库可能马上崩溃:
sys@TQGZS> alter system switch logfile;
alter system switch logfile
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
⑶ 可以从警告日志中获得部分详细信息:
Sun Dec 20 21:01:57 2009
Errors in file /u01/oracle/admin/tqgzs/bdump/tqgzs_arc1_5411.trc:
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/u01/oracle/oradata/tqgzs/redo02.log'
ORA-27037: unable to obtain file status
Linux Error: 2: No such file or directory
Additional information: 3
Sun Dec 20 21:01:57 2009
⑷ 此时启动数据库,数据库会提示日志丢失:
idle> startup
ORACLE instance started.Total System Global Area 285212672 bytes
Fixed Size 1218992 bytes
Variable Size 83887696 bytes
Database Buffers 197132288 bytes
Redo Buffers 2973696 bytes
Database mounted.
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/u01/oracle/oradata/tqgzs/redo02.log'
⑸ 此时在MOUNT状态,可以查看各日志组及日志文件的状态:
idle> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 142 52428800 1 NO CURRENT 6278352 20-DEC-09
3 1 141 52428800 1 NO INACTIVE 6278348 20-DEC-09
2 1 140 52428800 1 NO INACTIVE 6278311 20-DEC-09idle> select * from v$logfile;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------------------------------------ ---
3 ONLINE /u01/oracle/oradata/tqgzs/redo03.log NO
2 ONLINE /u01/oracle/oradata/tqgzs/redo02.log NO
1 ONLINE /u01/oracle/oradata/tqgzs/redo01.log NO可以注意到,v$log和v$logfile中依然有redo02记录。
⑹ 数据库处于归档模式下,清楚该未完成归档的日志组(redo02)后,即可启动数据库:
idle> alter database clear unarchived logfile group 2;
Database altered.
idle> alter database open;
Database altered.
idle> conn / as sysdba
Connected.
sys@TQGZS>
如果数据库在非归档模式下,使用如下命令强制清除:
alter database clear logfile group 2;
打开数据库之后,再次查询v$log和v$logfile视图,可以看到GROUP#=2已经为CURRENT了,一切恢复正常。
sys@TQGZS> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 142 52428800 1 YES INACTIVE 6278352 20-DEC-09
3 1 141 52428800 1 YES INACTIVE 6278348 20-DEC-09
2 1 143 52428800 1 NO CURRENT 6278714 20-DEC-09
sys@TQGZS> select * from v$logfile;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------------------------------------ ---
3 ONLINE /u01/oracle/oradata/tqgzs/redo03.log NO
2 ONLINE /u01/oracle/oradata/tqgzs/redo02.log NO
1 ONLINE /u01/oracle/oradata/tqgzs/redo01.log NO
sys@TQGZS> alter system switch logfile;
System altered.
sys@TQGZS> alter system switch logfile;
System altered.
sys@TQGZS> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 145 52428800 1 NO CURRENT 6280518 20-DEC-09
3 1 144 52428800 1 YES ACTIVE 6280516 20-DEC-09
2 1 143 52428800 1 YES ACTIVE 6278714 20-DEC-09
2. 丢失活动或当前日志文件的恢复:
虽然Oracle通过日志文件保证提交成功的数据不丢失,但是在故障中我们可能会损失当前的(CURRENT)日志文件,这又可分为两种情况。
① 在损失当前日志时,如果数据库是正常关闭的:
由于关闭数据库前,Oracle会执行全面检查点,当前日志在实例恢复中可以不再需要。
在Oracle 8i中,可以通过如下步骤恢复(非归档模式下测试过程):
> select * from v$log;
> shutdown immediate;
> ! mv /u01/oracle/oradata/tqgzs/redo* /tmp
> startup
> alter database clear logfile group 1;
> alter database clear logfile group 2;
> alter database clear logfile group 3;
> alter database open;
在Oracle 9i中,可能无法对于当前日志进行Clear,需要通过Until Cancel恢复后,Resetlogs打开,以下是一个简单的测试过程:
> ! rm /u01/oracle/oradata/tqgzs/redo0*
> startup
> alter database clear logfile group 1;
> alter database clear unarchived logfile group 2;
alter database clear unarchived logfile group 2
*
ERROR at line 1:
ORA-00313: open failed for members of log group 2 of thread 1
ORA-00312: online log 2 thread 1: '/u01/oracle/oradata/tqgzs/redo02.log'
ORA-27037: unable to obtain file status
Linux Error: 2: No such file or directory
Additional information: 3
> recover database until cancel;
> alter database open resetlogs;
② 在损失当前日志时,如果数据库是异常关闭的:
那么Oracle在进行实例恢复时必须要求当前日志,否则Oracle将无法保证提交成功的数据不丢失(也就意味着Oracle会丢失数据),在这种情况下,Oracle数据库将无法启动。
对于这种情况,通常需要从备份中恢复数据文件,通过应用归档日志文件向前推演,直到最后一个完好的日志文件,然后可以通过resetlogs启动数据库完成恢复。丢失的数据就是损坏的日志文件中的数据。这种恢复方式与以上介绍的方法类似,不再赘述。
可是不幸的是,很多数据库是从不备份的,那么在面对这种情况时,Oracle提供给我们一种内部手段可以用于强制性数据库打开,忽略一致性等问题,在打开数据库之后,Oracle建议导出(exp)数据,然后重建数据库,再导入(imp)数据,完成灾难恢复。
在继续之前,我愿意提及一下我经常强调的DBA四大守则之一:备份重于一切。要知道系统总是要崩溃的,没有有效的备份只是等哪一天死而已。如果说有什么事可以让DBA在深夜惊醒的话,那就是“没有备份”。
Oracle有一类具有特殊作用的隐含参数,其中一个参数是_allow_resetlogs_corruption,来看一下这个参数的说明:
sys@TQGZS> @GetParDescrb.sql
Enter value for par: _allow_resetlogs_corruption
old 4: AND x.ksppinm LIKE '%&par%'
new 4: AND x.ksppinm LIKE '%_allow_resetlogs_corruption%'
NAME VALUE DESCRIB
------------------------------ -------------------- ------------------------------------------------------------
_allow_resetlogs_corruption FALSE allow resetlogs even if it will cause corruption
该参数的含义是,允许在破坏一致性的情况下强制重置日志,打开数据库。_allow_resetlogs_corruption将使用所有数据文件最旧的SCN打开数据库,所以通常需要保证SYSTEM表空间拥有最旧的SCN。在强制打开数据库后,可能因为各种原因伴随出现ORA-600错误,有些可以依据常规途径解决。
步骤如下:
> alter system set "_allow_resetlogs_corruption"=true scope=spfile;
> shutdown immediate;
> startup mount;
> recover database using backup controlfile until cancel;
canel
> alter database open resetlogs;
> shutdown immediate;
> startup
幸运的时候数据库就可以成功OPEN,如果不幸则可能会遇到一系统的ORA-600错误(最常见的是2662错误),此时就需要使用多种手段继续进行调整恢复。
如果注意观察alert日志,可能会发现类似以下日志:
Fri Jun 10 16:30:25 2005
alter database open resetlogs
Fri Jun 10 16:30:25 2005
RESETLOGS is being done without consistancy checks. This may result
in a corrupted database. The database should be recreated.
RESETLOGS after incomplete recovery UNTIL CHANGE 240677200
Resetting resetlogs activation ID 3171937922 (0xbd0fee82)
不一致恢复最后恢复到的Change号是240677200。
Oracle告诉我们,强制resetlogs跳过了一致性检查,可能导致数据库损坏,数据库应当重建。而且此方法应该在Oracle技术支持的指导之下进行,否则Oracle将不对采用此类方式进行恢复的数据库进行支持。
DBA需要时刻铭记的一个工作习惯是,在重要操作或故障处理前,保留现场。也就是说在进行以上类似恢复等工作前,我们应当对数据库进行冷备份,这样在恢复尝试失败后,也仍然可以回退到之前的状态。
- The End -