_disable_logging对于归档数据库的影响
在归档数据库下,如果设置了 _disable_logging=true,那么数据库就会将所有的online redo logfile标记为corrput,从而在归档数据库下不能够正常的归档了,因此,每次需要当数据库中所有的日志组归档状态都为“NO”,且STATUS列的值出现n-1个“INACTIVE”和一个“CURRENT”时,即,除了当前日志外,其余所有的日志都是不活动且没有归档的时候,对数据库的所有操作(只要产生的日志超过current日志的可用大小的时候,也就是需要发生日志切换的时候)就会hang。
上述结论可以很容易的得到证实,首先我们检查数据库的状态,看它是否已经处在归档模式了,如果仍然处于非归档模式的话,请先将数据库改为归档方式(具体的方法不是这里讨论的重点,就不赘述了):
sys@TSMISC02> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /oracle/oradata/TSMISC02/archive
Oldest online log sequence 1595
Next log sequence to archive 1597
Current log sequence 1597
sys@TSMISC02>
再检查一下当前的日志文件信息:
sys@TSMISC02> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 1597 2097152 1 NO CURRENT 6913201 11-APR-06
2 1 1595 2097152 1 YES INACTIVE 6889512 11-APR-06
3 1 1596 2097152 1 YES INACTIVE 6901361 11-APR-06
Elapsed: 00:00:00.01
sys@TSMISC02>
sys@TSMISC02> col member for a50
sys@TSMISC02> select * from v$logfile;
GROUP# STATUS TYPE MEMBER
---------- ------- ------- --------------------------------------------------
1 ONLINE /oracle/oradata/TSMISC02/redo01.log
2 ONLINE /oracle/oradata/TSMISC02/redo02.log
3 ONLINE /oracle/oradata/TSMISC02/redo03.log
Elapsed: 00:00:00.00
sys@TSMISC02>
我们看到,当前的日志文件是日志组1(online redo log group 1),日志组2和日志组3都已经成功归档,并且状态是“INACTIVE”,也就是说,这两个组已经可以被循环使用了。
现在设置"_disable_logging"=true:
sys@TSMISC02> alter system set "_disable_logging"=true scope=both;
System altered.
Elapsed: 00:00:00.00
sys@TSMISC02>
然后,再创建一些大表等等,然后观察日志的情况:
sys@TSMISC02> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 1597 2097152 1 NO ACTIVE 6913201 11-APR-06
2 1 1598 2097152 1 NO CURRENT 6919313 11-APR-06
3 1 1596 2097152 1 YES INACTIVE 6901361 11-APR-06
Elapsed: 00:00:00.00
sys@TSMISC02> select * from v$logfile;
GROUP# STATUS TYPE MEMBER
---------- ------- ------- --------------------------------------------------
1 ONLINE /oracle/oradata/TSMISC02/redo01.log
2 ONLINE /oracle/oradata/TSMISC02/redo02.log
3 ONLINE /oracle/oradata/TSMISC02/redo03.log
Elapsed: 00:00:00.00
sys@TSMISC02>
我们观察到,系统已经发生了日志切换,当前系统正在使用的日志组已经是group 2了,而刚才的那个group 1是没有完成归档的状态,即,没有归档且状态为active。
这时候,实际上数据库已经出现问题了,但是由于还有其他可用的日志组可以继续使用,因此在前台sqlplus的使用界面上并没有报错,但是如果你检查alert.log,就会发现系统已经开始不断的报类似下面的错误信息了:
Tue Apr 11 13:50:07 2006
ALTER SYSTEM SET _disable_logging=TRUE SCOPE=BOTH;
Tue Apr 11 14:09:35 2006
ARC0: Evaluating archive log 1 thread 1 sequence 1597
ARC0: Beginning to archive log 1 thread 1 sequence 1597
Creating archive destination LOG_ARCHIVE_DEST_1: '/oracle/oradata/TSMISC02/archive/1_1597.dbf'
Tue Apr 11 14:09:35 2006
Thread 1 advanced to log sequence 1598
Current log# 2 seq# 1598 mem# 0: /oracle/oradata/TSMISC02/redo02.log
Tue Apr 11 14:09:35 2006
ARC0: Log corruption near block 3740 change 0 time ?
ARC0: All Archive destinations made inactive due to error 354
Tue Apr 11 14:09:35 2006
Errors in file /oracle/admin/TSMISC02/bdump/tsmisc02_arc0_9459.trc:
ORA-00354: corrupt redo log block header
ORA-00353: log corruption near block 3740 change 0 time 04/11/2006 13:49:56
ORA-00312: online log 1 thread 1: '/oracle/oradata/TSMISC02/redo01.log'
ARC0: Archiving not possible: error count exceeded
ARC0: Failed to archive log 1 thread 1 sequence 1597
ARCH: Archival stopped, error occurred. Will continue retrying
。。。。。。。
并且系统会不断的尝试将redo01.log日志文件归档,但是由于这个文件总是不能被成功归档,所以数据库就不断的循环和重复上面的错误信息。
此时,如果你是用dbv来检查一下redo01.log日志文件的话,你会发现类似下面的信息:
DBVERIFY - Verification complete
Total Pages Examined : 4096
Total Pages Processed (Data) : 0
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 4
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 0
Total Pages Marked Corrupt : 4096
Total Pages Influx : 2
Highest block SCN : 1 (0.1)
这里我们发现,整个日志文件中所有的块都被标记为损坏状态了!
由此我们可以看到_disable_logging=true对于归档数据库的一个破坏作用之一就是将整个数据库的redo log file都标记为损坏。
那么现在我们应该怎么办呢?首先我们需要使用alert system命令将_disable_logging参数设置为false,然后,依次对所有没有归档的日志做清理未归档日志的工作:
alter database clear unarchived logfile '/oracle/oradata/TSMISC02/redo01.log';
alter database clear unarchived logfile '/oracle/oradata/TSMISC02/redo02.log';
......
注意:
初始化日志文件的语法:
ALTER DATABASE [database]
CLEAR [UNARCHIVED] LOGFILE
{GROUP integer|('filename'[, 'filename']...)}
[,{GROUP integer|('filename'[, 'filename']...)}]...
无论联机重做日志文件是否归档,都可以清除它。
但是,在其没有归档时,必须包含关键字UNARCHIVED。
由于篇幅关系,这里进对部分操作说明一下:
sys@TSMISC02> alter system set "_disable_logging"=false scope=both;
System altered.
Elapsed: 00:00:00.01
sys@TSMISC02>
sys@TSMISC02> alter database clear unarchived logfile '/oracle/oradata/TSMISC02/redo02.log';
Database altered.
Elapsed: 00:00:00.18
sys@TSMISC02> alter database clear unarchived logfile '/oracle/oradata/TSMISC02/redo03.log';
Database altered.
Elapsed: 00:00:00.17
sys@TSMISC02>
sys@TSMISC02> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
1 1 1600 2097152 1 NO CURRENT 6950639 12-APR-06
2 1 0 2097152 1 YES UNUSED 6919313 11-APR-06
3 1 0 2097152 1 YES UNUSED 6922631 11-APR-06
Elapsed: 00:00:00.00
sys@TSMISC02>
其实,需要清理哪些日志,你可以根据alert.log的报错来做,比如这里,当你清理了日志组1,alert中就开始报关于group 2不能归档的信息;当你清理了日志组2,alert中就开始报关于group 3不能归档的信息。。。,以此类推,所有的日志组都被初始化后,数据库就恢复正常了。当然这时后你需要做一个数据库的全备,因为之前的数据库备份已经无效了。
注意:如果对当前的日志(状态未“CURRENT”的日志组做clear unarchived logfile的操作会有类似下面的报错:
sys@TSMISC02>alter database clear unarchived logfile '/oracle/oradata/TSMISC02/redo01.log';
alter database clear unarchived logfile '/oracle/oradata/TSMISC02/redo01.log'
*
ERROR at line 1:
ORA-01624: log 1 needed for crash recovery of thread 1
ORA-00312: online log 1 thread 1: '/oracle/oradata/TSMISC02/redo01.log'
Elapsed: 00:00:00.05
sys@TSMISC02>
你只需要使用alter system switch logfile,然后再做clear unarchived logfile的操作就可以了。
综上,我们已经验证了本章界最初的结论。