Redo log:是用于记录数据库所有变化信息的文件,只要有底层的块变化就会产生信息,当遇到需要恢复的场景,我们可以利用这些redo log进行实例恢复和介质恢复。Redo log日志通常情况下都是分成若干组存在数据库中,每个组都会有2个以上的成员互为镜像(保证高可用),每个组循环切换使用。下面我们来看看redo log的恢复操作。
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 1 52428800 YES INACTIVE
2 1 52428800 NO CURRENT
3 1 52428800 YES UNUSED
现在有3个redo组,每个组只有一个成员,每个成员大小为50M,显然这是不合理的,保证每个日志文件组中包含不少于一个日志文件成员,那么我们现在可以添加一下,要记住哦如果在生产环境下,redo日志组成员要放在不同的磁盘上,防止磁盘级损坏。
[oracle@leonarding1LEO1]$ mkdir disk2 我们创建一个disk2目录模拟第二块磁盘
SYS@LEO1>alterdatabase add logfile member
'/u02/app/oracle/oradata/LEO1/disk2/redo01_b.log'to group 1, 给组1添加成员
'/u02/app/oracle/oradata/LEO1/disk2/redo02_b.log'to group 2, 给组2添加成员
'/u02/app/oracle/oradata/LEO1/disk2/redo03_b.log'to group 3; 给组3添加成员
2 3 4
Database altered.
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 2 52428800 YES INACTIVE
2 2 52428800 NO CURRENT
3 2 52428800 YES UNUSED
SYS@LEO1>selectgroup#,member,status from v$logfile;
GROUP# MEMBER STATUS
------------------------------------------------------------ -------
1 /u02/app/oracle/oradata/LEO1/redo01.log
2/u02/app/oracle/oradata/LEO1/redo02.log
3/u02/app/oracle/oradata/LEO1/redo03.log
1/u02/app/oracle/oradata/LEO1/disk2/redo01_b.log INVALID
2/u02/app/oracle/oradata/LEO1/disk2/redo02_b.log INVALID
3/u02/app/oracle/oradata/LEO1/disk2/redo03_b.log INVALID
6 rows selected.
Ok,日志组成员添加完成,每个大小和原来成员一致50M,路径放在disk2目录上
SYS@LEO1>archivelog list 已经是归档模式
Database logmode Archive Mode
Automaticarchival Enabled
Archivedestination /u02/app/oracle/archdata
我们做几次日志切换,把所有redo log 都使用一遍
SYS@LEO1>altersystem switch logfile;
System altered.
SYS@LEO1>altersystem switch logfile;
System altered.
SYS@LEO1>altersystem switch logfile;
System altered.
SYS@LEO1>archivelog list
Database logmode Archive Mode
Automaticarchival Enabled
Archivedestination /u02/app/oracle/archdata
Oldest online logsequence 3
Next log sequenceto archive 5
Current logsequence 5
我们切换了3次生成了3个归档日志2 3 4号,下一次该归档的是5号
[oracle@leonarding1archdata]$ ll
total 30708
-rw-r----- 1oracle asmadmin 222720 Apr 26 21:051_1_813790699.dbf
-rw-r-----1 oracle asmadmin 17069056 Apr 28 07:03 1_2_813790699.dbf
-rw-r-----1 oracle asmadmin 1024 Apr 28 07:031_3_813790699.dbf
-rw-r-----1 oracle asmadmin 3072 Apr 28 07:031_4_813790699.dbf
现在我们看到已经切换到组2为当前redo 组了,组1和组3已经全部归档
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 2 52428800 YES INACTIVE
2 2 52428800 NO CURRENT
3 2 52428800 YES INACTIVE
如果想把inactive的日志恢复首先要了解日志各种状态含义
Current:Oracle当前正在使用的redo log,就是LGWR进程正在写入的redo log,在实例恢复时会用到此日志,这个redo log记录着数据库最后的SCN号。
Active:表示日志是活动的但不是当前正在使用的redolog,active意味着checkpoint动作尚未完成(脏数据还没有完全刷到磁盘上)or 归档模式下该日志的内容还没有完全归档,这两种情况下都会让日志为active状态,在实例恢复时也会用到此日志文件,因此该日志文件不能被覆盖。
Inactive:表示日志是不活动的,checkpoint动作已经完成,日志内容已经完全归档,可以被后续redo数据覆盖,实例恢复时不在需要,但在介质恢复时可能需要
Unused:表示日志从未使用过,里面没有任何的旧数据,可能是刚刚添加的日志 or resetlogs之后被重置的日志。
Clearing:表示日志在alter database clear logfile命令之后被重新创建为一个空日志,原来日志中的内容被全部清空,日志被清空后状态重置为unused。
Clearing_current:表示日志在current状态下被清空了,如果发生切换,在写日志文件头时会报一个I/O错误,一定要警惕这种状态,可能会导致数据永久丢失。
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 2 52428800 YES INACTIVE
2 2 52428800 NO CURRENT
3 2 52428800 YES INACTIVE
现在是第一组和第三组为inactive,我们直接删除第一组中的一个成员redo01.log
[oracle@leonarding1LEO1]$ rm redo01.log 操作系统级别删除
由于是不活动日志此时数据库不受影响会继续运行,我们关库再重启看看会发生什么
SYS@LEO1>shutdownimmediate 关库
Database closed.
Databasedismounted.
ORACLE instanceshut down.
SYS@LEO1>startup 重启
ORACLE instancestarted.
Total SystemGlobal Area 471830528 bytes
Fixed Size 2214456 bytes
Variable Size 171967944 bytes
DatabaseBuffers 289406976 bytes
Redo Buffers 8241152 bytes
Database mounted.
Database opened.
SYS@LEO1>selectgroup#,member,status from v$logfile;
GROUP# MEMBER STATUS
------------------------------------------------------------ -------
1/u02/app/oracle/oradata/LEO1/redo01.log INVALID
2 /u02/app/oracle/oradata/LEO1/redo02.log
3/u02/app/oracle/oradata/LEO1/redo03.log
1/u02/app/oracle/oradata/LEO1/disk2/redo01_b.log
2/u02/app/oracle/oradata/LEO1/disk2/redo02_b.log
3 /u02/app/oracle/oradata/LEO1/disk2/redo03_b.log
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 2 52428800 YES INACTIVE
2 2 52428800 NO CURRENT
3 2 52428800 YES INACTIVE
6 rows selected.
SYS@LEO1>archivelog list
Database logmode Archive Mode
Automaticarchival Enabled
Archivedestination /u02/app/oracle/archdata
Oldest online logsequence 3
Next log sequenceto archive 5
Current logsequence 5
没有报错信息,验证奇迹的时刻,按理说oracle在检测到redolog日志丢失的时候会启动告警,实际上什么也没有发生,不科学,难道oracle没有检测到redolog丢失嘛???
Errors in file/u02/app/oracle/diag/rdbms/leo1/LEO1/trace/LEO1_lgwr_10850.trc:
ORA-00313:open failed for members of log group 1 of thread 1
ORA-00312:online log 1 thread 1: '/u02/app/oracle/oradata/LEO1/redo01.log'
ORA-27037: unableto obtain file status
Linux-x86_64Error: 2: No such file or directory
非也非也,我们在alert日志中发现了告警踪迹“打开组1成员失败并且指出了失败文件路径”,那为什么在sqlplus中没有告警信息呢???从Oracle设计的理念上可以窥视出,它想让数据库尽可能的活下来,只要不需要的动作就可以先忽略掉(尽管已经检测出来了,会在状态上标注为invalid)。那么ok,我们开始恢复
【参】Books->Administrator’sGuide -> 6 Managing the Redo Log ->Dropping RedoLog Groups and Members
SYS@LEO1>shutdownimmediate 关库
Database closed.
Databasedismounted.
ORACLE instanceshut down.
SYS@LEO1>startupmount 启动到mount状态
ORACLE instancestarted.
Total SystemGlobal Area 471830528 bytes
Fixed Size 2214456 bytes
Variable Size 171967944 bytes
DatabaseBuffers 289406976 bytes
Redo Buffers 8241152 bytes
Database mounted.
刚才我们是从操作系统层面删除的,但控制文件中还保留了redolog信息,我们在从数据库层面删除
SYS@LEO1>ALTERDATABASE DROP LOGFILE MEMBER '/u02/app/oracle/oradata/LEO1/redo01.log';
Database altered.
切记一定要先删除,再创建否则会报文件已经存在的错误:
ORA-01577: cannotadd log file '/u02/app/oracle/oradata/LEO1/redo01.log' – file already part ofdatabase
SYS@LEO1>alterdatabase add logfile member '/u02/app/oracle/oradata/LEO1/redo01.log' to group1;
Database altered.
SYS@LEO1>alterdatabase open; 打开数据库
Database altered.
SYS@LEO1>selectgroup#,member,status from v$logfile;
GROUP# MEMBER STATUS
------------------------------------------------------------ -------
1/u02/app/oracle/oradata/LEO1/redo01.log INVALID
2/u02/app/oracle/oradata/LEO1/redo02.log
3/u02/app/oracle/oradata/LEO1/redo03.log
1/u02/app/oracle/oradata/LEO1/disk2/redo01_b.log
2/u02/app/oracle/oradata/LEO1/disk2/redo02_b.log
3/u02/app/oracle/oradata/LEO1/disk2/redo03_b.log
怎么还是显示invalid无效呢,上面说过只要不需要就可以先忽略掉
6 rows selected.
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 2 52428800 YES INACTIVE
2 2 52428800 NO CURRENT
3 2 52428800 YES INACTIVE
我们做2次切换,把当前组切换为组1
SYS@LEO1>alter systemswitch logfile;
System altered.
SYS@LEO1>altersystem switch logfile;
System altered.
这次是不是状态变成正常的啦,用到了自动监测,到此我们模拟inactive日志恢复完成
SYS@LEO1>selectgroup#,member,status from v$logfile;
GROUP# MEMBER STATUS
------------------------------------------------------------ -------
1/u02/app/oracle/oradata/LEO1/redo01.log
2/u02/app/oracle/oradata/LEO1/redo02.log
3/u02/app/oracle/oradata/LEO1/redo03.log
1/u02/app/oracle/oradata/LEO1/disk2/redo01_b.log
2 /u02/app/oracle/oradata/LEO1/disk2/redo02_b.log
3/u02/app/oracle/oradata/LEO1/disk2/redo03_b.log
附加另一种方法,还可以先删除损坏组,在增加新组的方式来恢复
SYS@LEO1>ALTERDATABASE DROP LOGFILE GROUP 3;
Database altered.
这个只是在控制文件上删除,你还需要在操作系统层面上删除
[oracle@leonarding1LEO1]$ rm redo03.log
[oracle@leonarding1disk2]$ rm redo03_b.log
SYS@LEO1>ALTERDATABASE ADD LOGFILE GROUP 5('/u02/app/oracle/oradata/LEO1/redo05.log','/u02/app/oracle/oradata/LEO1/disk2/redo05_b.log')SIZE 50M;
Database altered.
我们增加了第五组,状态良好
SYS@LEO1>selectgroup#,member,status from v$logfile;
GROUP# MEMBER STATUS
------------------------------------------------------------ -------
1/u02/app/oracle/oradata/LEO1/redo01.log
2/u02/app/oracle/oradata/LEO1/redo02.log
5/u02/app/oracle/oradata/LEO1/redo05.log
1/u02/app/oracle/oradata/LEO1/disk2/redo01_b.log
2/u02/app/oracle/oradata/LEO1/disk2/redo02_b.log
5 /u02/app/oracle/oradata/LEO1/disk2/redo05_b.log
6 rows selected.
新添加的第五组为unused状态,还没有使用
SYS@LEO1>selectgroup#,members,bytes,archived,status from v$log;
GROUP# MEMBERS BYTES ARC STATUS
-------------------- ---------- --- ----------------
1 2 52428800 NO CURRENT
2 2 52428800 YES INACTIVE
5 2 52428800 YES UNUSED
补充:使用alter database clear logfile n 命令恢复 inactive状态损坏的日志文件
Clearing:表示日志在alter database clear logfile命令之后被重新创建为一个空日志,原来日志中的内容被全部清空,日志被清空后状态重置为unused。
原理:这个方法的恢复原理就是把损坏的日志文件重新创建一次,创建成一个新的空日志,表面上看就是把日志内容给清空了保证一致性,因为这种状态的redolog已经归档完毕,里面的数据已经没有意义了,清空or覆盖都不影响数据库的运行。
举例
SQL> alterdatabase clear logfile group 1;
Database altered.
SQL> alter database open;
Database altered.
小结:在进行恢复redolog日志之前一定要先掌握其状态要领,了解redolog正处于什么状态,会不会丢失数据,根据其特点采用合理的恢复方案。