Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3396726
  • 博文数量: 631
  • 博客积分: 10716
  • 博客等级: 上将
  • 技术积分: 8397
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-01 22:35
文章分类

全部博文(631)

文章存档

2020年(2)

2019年(22)

2018年(4)

2017年(37)

2016年(22)

2015年(1)

2013年(12)

2012年(20)

2011年(19)

2010年(20)

2009年(282)

2008年(190)

分类: Oracle

2011-04-11 20:46:34

REDO文件丢失或者损坏的恢复


  • REDO文件的功能描述
REDO文件存储所有数据库的变更内容和每一次变更所需的重做脚本,是数据库不可缺少的一部分,如果REDO GROUP中只有一个REDO文件,同时这个REDO文件被损坏,则系统切换到这个REDO GROUP时,数据库将直接DOWN;如果REDO GROUP中有多个REDO文件,其中一个或者多个REDO被损坏,只要该组中还有一个好的REDO文件,则系统将报警(写入alert.log文档中),数据库仍然可以超常运行。
REDO文件在数据库恢复时提供前滚所需的内容。


查看REDO 相关信息的视图有:V$LOG,V$LOGFILE,V$INSTANCE_RECOVERY
SQL> DESC V$INSTANCE_RECOVERY;
名称 是否为空? 类型
----------------------------------------- -------- ------
RECOVERY_ESTIMATED_IOS NUMBER
ACTUAL_REDO_BLKS NUMBER
TARGET_REDO_BLKS NUMBER
LOG_FILE_SIZE_REDO_BLKS NUMBER
LOG_CHKPT_TIMEOUT_REDO_BLKS NUMBER
LOG_CHKPT_INTERVAL_REDO_BLKS NUMBER
FAST_START_IO_TARGET_REDO_BLKS NUMBER
TARGET_MTTR NUMBER
ESTIMATED_MTTR NUMBER
CKPT_BLOCK_WRITES NUMBER
OPTIMAL_LOGFILE_SIZE NUMBER
ESTD_CLUSTER_AVAILABLE_TIME NUMBER
WRITES_MTTR NUMBER
WRITES_LOGFILE_SIZE NUMBER
WRITES_LOG_CHECKPOINT_SETTINGS NUMBER
WRITES_OTHER_SETTINGS NUMBER
WRITES_AUTOTUNE NUMBER
WRITES_FULL_THREAD_CKPT NUMBER
一般情况下,最好有3-5REDO GROUP,每个REDO GROUP中有两个成员,放在不同的磁盘资源上。同一个REDO GROUP 中的REDO文件的大小尽量设置为相同,否则系统以最小的一个为基准,比较浪费空间。各个REDO GROUP 的大小也最好一致。


  • REDO文件恢复实例
2.1查看REDO 相关视图
SQL> select * from v$log;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- -------------------
1 1 14 10485760 2 YES ACTIVE 1304089 2006-07-06 12:33:59
2 1 15 10485760 2 YES INACTIVE 1314889 2006-07-06 15:55:10
3 1 16 10485760 2 NO CURRENT 1323514 2006-07-07 08:33:21
STATUS状态的解释:
CURRENT: 当前的REDO文件,REDO BUFFER 的内容有LGWR进程写入当前REDO文件,如果丢失该组文件,会造成数据的丢失.
ACTIVE : 文件中含有的内容还没有写入到ARCHIVELOG文件中,如果丢失该组文件也会造成数据的丢失.
INACTIVE: 已经归档,丢失文件不会造成数据丢失,不过在做数据库的恢复时,该组文件可以用来做前滚操作.
SQL> SELECT * FROM V$LOGFILE ORDER BY GROUP#;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------ ---
1 ONLINE C:\ORADATA\AIDU\REDO01.LOG NO
1 ONLINE C:\ORADATA\AIDU\REDO01B.LOG NO
2 ONLINE C:\ORADATA\AIDU\REDO02.ORA NO
2 ONLINE C:\ORADATA\AIDU\REDO02B.ORA NO
3 ONLINE C:\ORADATA\AIDU\REDO03.LOG NO
3 ONLINE C:\ORADATA\AIDU\REDO03B.LOG NO
已选择6行。
可以看到,当前数据库有3REDO GROUP,每个GROUP 含有两个MEMBER(REDO文件).

2.2 增加REDO GROUP
SQL> alter database add logfile group 4 'C:\ORADATA\AIDU\REDO04.ORA' SIZE 10M REUSE;
数据库已更改。
SQL> SELECT * FROM V$LOGFILE ORDER BY GROUP#;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------ ---
1 ONLINE C:\ORADATA\AIDU\REDO01B.LOG NO
1 ONLINE C:\ORADATA\AIDU\REDO01.LOG NO
2 ONLINE C:\ORADATA\AIDU\REDO02.ORA NO
2 ONLINE C:\ORADATA\AIDU\REDO02B.ORA NO
3 ONLINE C:\ORADATA\AIDU\REDO03B.LOG NO
3 ONLINE C:\ORADATA\AIDU\REDO03.LOG NO
4 ONLINE C:\ORADATA\AIDU\REDO04.ORA NO
已选择7行。

2.3 删除REDO GROUP
SQL> ALTER DATABASE DROP LOGFILE GROUP 4;
数据库已更改。
SQL> SELECT * FROM V$LOGFILE ORDER BY GROUP#;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------ ---
1 ONLINE C:\ORADATA\AIDU\REDO01.LOG NO
1 ONLINE C:\ORADATA\AIDU\REDO01B.LOG NO
2 ONLINE C:\ORADATA\AIDU\REDO02.ORA NO
2 ONLINE C:\ORADATA\AIDU\REDO02B.ORA NO
3 ONLINE C:\ORADATA\AIDU\REDO03.LOG NO
3 ONLINE C:\ORADATA\AIDU\REDO03B.LOG NO
已选择6行。

2.4 REDO GROUP中增加REDO文件(MEMBER
SQL> ALTER DATABASE ADD LOGFILE MEMBER 'C:\ORADATA\AIDU\REDO01C.LOG' TO GROUP 1;
数据库已更改。
SQL> SELECT * FROM V$LOGFILE ORDER BY GROUP#;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------ ---
1 INVALID ONLINE C:\ORADATA\AIDU\REDO01C.LOG NO
1 ONLINE C:\ORADATA\AIDU\REDO01.LOG NO
1 ONLINE C:\ORADATA\AIDU\REDO01B.LOG NO
2 ONLINE C:\ORADATA\AIDU\REDO02.ORA NO
2 ONLINE C:\ORADATA\AIDU\REDO02B.ORA NO
3 ONLINE C:\ORADATA\AIDU\REDO03.LOG NO
3 ONLINE C:\ORADATA\AIDU\REDO03B.LOG NO
已选择7行。
我们注意到新建的MEMBER的状态为INVALID,这个不用担心,等下次切换到该组,然后状态就会修改为正常。

2.5 REDO GROUP中删除REDO 文件(MEMBER
SQL> ALTER DATABASE DROP LOGFILE MEMBER 'C:\ORADATA\AIDU\REDO01C.LOG';
数据库已更改。
SQL> SELECT * FROM V$LOGFILE ORDER BY GROUP#;
GROUP# STATUS TYPE MEMBER IS_
---------- ------- ------- ------------------------------ ---
1 ONLINE C:\ORADATA\AIDU\REDO01.LOG NO
1 ONLINE C:\ORADATA\AIDU\REDO01B.LOG NO
2 ONLINE C:\ORADATA\AIDU\REDO02.ORA NO
2 ONLINE C:\ORADATA\AIDU\REDO02B.ORA NO
3 ONLINE C:\ORADATA\AIDU\REDO03.LOG NO
3 ONLINE C:\ORADATA\AIDU\REDO03B.LOG NO
已选择6行。
注意: 不可以删除REDO GROUP 中所有的REDO 文件,这样会报错,如下所示:
SQL> ALTER DATABASE DROP LOGFILE MEMBER 'C:\ORADATA\AIDU\REDO01.LOG';
数据库已更改。
SQL> ALTER DATABASE DROP LOGFILE MEMBER 'C:\ORADATA\AIDU\REDO01B.LOG';
ALTER DATABASE DROP LOGFILE MEMBER 'C:\ORADATA\AIDU\REDO01B.LOG'
* 1 行出现错误:
ORA-00361: 无法删除最后一个日志成员 C:\ORADATA\AIDU\REDO01B.LOG ( 1)

2.6 已经归档的REDO文件损坏的恢复
所谓已经归档的REDO文件就是在V$LOG视图中状态为INACTIVEREDO文件。
这些文档的丢失,不会对数据库造成任何影响,但需要及时的恢复,否则切换到这个组时将会发生错误。
解决问题有两个办法:
    A.删除这个REDO GROUP,记住删除后数据库的REDO GROUP数目不应小于2,如果当前REDO GROUP数目为2,则不可以使用这个办法。
      B.在组中增加新的同样大小的REDO文件,然后删除原来的MEMBER。增加、删除REDO文件的方法见上面的2.4,2.5


2.7没有归档的REDO文件损坏的恢复

2.7.1 简述
所谓没有归档的REDO文件就是在V$LOG视图中状态为ACTIVE,CURRENTREDO文件。如果没有归档的REDO GROUP中含有多个REDO 文件,丢失或者损坏的只是部分REDO文件,则可以通过复制正常的REDO文件,覆盖损坏的REDO文件的方式解决问题,数据不会丢失,不用做恢复操作。
如果没有归档的REDO GROUP组中所有的REDO文件都丢失或者损坏,将会导致数据库数据丢失,如果没有归档的REDO GROUP 为当前组,则数据库立即DOWN机。当这个情况发生时,就意味着数据的丢失,我们只能将数据库恢复到前一次的归档日志切换时刻。


2.7.2 建立测试环境
检查当前的REDO GROUP为第1.
SQL> SELECT * FROM V$LOG;
GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIME
------------- -------------------
1 1 17 10485760 1 NO CURRENT
1333209 2006-07-07 11:47:23
2 1 15 10485760 2 YES INACTIVE
1314889 2006-07-06 15:55:10
3 1 16 10485760 2 YES INACTIVE
1323514 2006-07-07 08:33:21
建立一个测试表,这个数据库的变化存放在当前的REDO文件中。
SQL> CREATE TABLE AIDU.TEST_FOR_REDO AS SELECT * FROM AIDU.TEST02;
表已创建。

2.7.3 模拟灾难发生
SQL> SHUTDOWN ABORT;
ORACLE 例程已经关闭
SQL>HOST DELETE C:ORADATAAIDUREDO01*.* #删除当前日志组的所有成员文件
SQL> STARTUP #启动数据库时将报找不到数据库文件的错误,数据库只能启动到MOUNT状态。
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE 例程已经启动。

Total System Global Area 268435456 bytes
Fixed Size 1248504 bytes
Variable Size 96469768 bytes
Database Buffers 167772160 bytes
Redo Buffers 2945024 bytes
数据库装载完毕。
ORA-00313: 无法打开日志组 1 (用于线程 1) 的成员
ORA-00312: 联机日志 1 线程 1: 'C:\ORADATA\AIDU\REDO01B.LOG'
ORA-27041: 无法打开文件
OSD-04002: 无法打开文件
O/S-Error: (OS 2) 系统找不到指定的文件。
SQL> SELECT OPEN_MODE FROM V$DATABASE;
OPEN_MODE
----------
MOUNTED

2.7.4 进行灾难恢复

尝试使用RESETLOG或者NORESETLOGS打开数据库,结果失败
SQL> alter database open resetlogs;
alter database open resetlogs
* 1 行出现错误:
ORA-01139: RESETLOGS 选项仅在不完全数据库恢复后有效
SQL> alter database open noresetlogs;
alter database open noresetlogs
* 1 行出现错误:
ORA-01139: RESETLOGS 选项仅在不完全数据库恢复后有效


尝试删除当前被破坏的REDO GROUP,结果失败
SQL> alter database drop logfile group 1;
alter database drop logfile group 1
*
1 行出现错误:
ORA-01623: 日志 1 是实例 aidu (线程 1) 的当前日志 - 无法删除
ORA-00312: 联机日志 1 线程 1: 'C:\ORADATA\AIDU\REDO01B.LOG'


清除当前日志组的内容,然后重新建立
SQL> ALTER DATABASE CLEAR UNARCHIVED LOGFILE GROUP 1;
* 1 行出现错误:
ORA-01624: 日志 1 是紧急恢复实例 aidu (线程 1) 所必需的
ORA-00312: 联机日志 1 线程 1: 'C:\ORADATA\AIDU\REDO01B.LOG'

这样我们只能做不完全的恢复了,恢复的方法有两个:

  • 使用RMAN或者手工进行基于CANCEL的恢复。
SQL>SHUTDOWN IMMEDIATE;
手工删除数据文件(DATAFILE
C:>RMAN TARGET /
RMAN>STARTUP MOUNT
RMAN>RUN{
ALLOCATE CHANNEL D1 TYPE DISK;
RESTORE DATABASE;
RECOVER DATABASE;
RELEASE CHANNEL D1;}
RMAN>ALTER DATABASE OPEN RESETLOGS;
这里不详细讨论RMAN的恢复。


  • 使用EXP,IMP进行恢复。
具体操作步骤如下:
SQL>SHUTDOWN IMMEDIATE;
init.ora中加入参数: _allow_resetlogs_corruption=TRUE
重新启动数据库,利用until cancel恢复
SQL>recover database until cancel;
Cancel
如果出错,不再理会,发出
SQL>alter database open resetlogs;
数据库被打开后,马上执行一个full export
shutdown数据库,去掉_all_resetlogs_corrupt参数
重建库
import并完成恢复
建议执行一下ANALYZE TABLE ...VALIDATE STRUCTURE CASCADE

oracle redo日志恢复

Oracle备份恢复中,redo的恢复相对来说还是比较简单的,只要保证每组的成员不止一个,出现问题的几率就相当小,即使出了问题我们也可按照不同的方法将他们恢复,所以如果碰到日志文件损坏,完全不必紧张!按照下面的方法来做,基本上都能搞定!

 

试验一:用命令清空日志组方法

1、  查看原来表中数据

SQL> conn test/test

Connected.

SQL> select * from test;

       TEL

----------

         1

         2

         3

2、插入新数据

SQL> insert into test values(4);

1 row created.

SQL> commit;

Commit complete.

SQL>

3、  正常关闭数据库

4、  利用os command删除所有redo文件

5、  启动数据库

SQL> startup

ORACLE instance started.

Total System Global Area  353862792 bytes

Fixed Size                   730248 bytes

Variable Size             285212672 bytes

Database Buffers           67108864 bytes

Redo Buffers                 811008 bytes

Database mounted.

ORA-00313: open failed for members of log group 1 of thread 1

ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'

6、  查看当前日志状态

SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS

---------- ---------- ---------- ---------- ---------- --- ----------------

FIRST_CHANGE# FIRST_TIME

------------- ----------

         1          1          2  104857600          1 YES INACTIVE

       487837 01-9 -05

         2          1          4  104857600          1 NO  CURRENT

       487955 01-9 -05

         3          1          3  104857600          1 YES INACTIVE

       487839 01-9 -05

看来redo01.log不是当前日志,对于这类非当前日志可以直接clear,系统会重新自动生成一个redo文件

7SQL> alter database clear logfile group 1;

Database altered.

7、  继续启动db

SQL> alter database open;

alter database open

*

ERROR at line 1:

ORA-00313: open failed for members of log group 2 of thread 1

ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'

8、  看来redo也得恢复,但是redo02是当前redo,直接clear是不行的

SQL> alter database clear logfile group 2;

alter database clear logfile group 2

*

ERROR at line 1:

ORA-00350: log 2 of thread 1 needs to be archived

ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'

9、  按照oracle的某些做法也是不行的

SQL> alter database clear unarchived logfile group 2 unrecoverable datafile;

alter database clear unarchived logfile group 2 unrecoverable datafile

*

ERROR at line 1:

ORA-00313: open failed for members of log group 2 of thread 1

ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'

ORA-27037: unable to obtain file status

SVR4 Error: 2: No such file or directory

Additional information: 3

10、              尝试从其他冷被分cp过来一个,再作clear,还是不行

SQL> host cp /T3/ORACLE/oradata2/ORA9/redo02.log /T3/ORACLE/oradata/ORA9/

SQL> alter database clear unarchived logfile group 2 unrecoverable datafile;

alter database clear unarchived logfile group 2 unrecoverable datafile

*

ERROR at line 1:

ORA-00322: log 2 of thread 1 is not current copy

ORA-00312: online log 2 thread 1: '/T3/ORACLE/oradata/ORA9/redo02.log'

SQL>

11、              但是对于非当前日志就都可以,下面看看redo03

SQL>  alter database clear logfile group 3;

Database altered.

结论:

如果数据库是正常shutdown,非当前日志都可以直接clear来重新生成,而且不丢失数据,因为正常关闭db,数据已经写入dbf文件了。唯独当前日志不可以,当前日志必须用其他方法恢复,不管是不是正常关闭,

方法二:用cancel模式恢复数据库

前面的出错提示,步骤都一样,唯独恢复的方法不一样

SQL> startup

ORACLE instance started.

Total System Global Area  353862792 bytes

Fixed Size                   730248 bytes

Variable Size             285212672 bytes

Database Buffers           67108864 bytes

Redo Buffers                 811008 bytes

Database mounted.

ORA-00313: open failed for members of log group 1 of thread 1

ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'

看看丢失了哪些redo

SQL> host ls /T3/ORACLE/oradarta/ORA9/redo*

/T3/ORACLE/oradarta/ORA9/redo*: No such file or directory

看来redo都丢了

直接recover

SQL> recover database until cancel;

Media recovery complete.

这个时候redo还没有生成

SQL> host ls /T3/ORACLE/oradata/ORA9/redo*

/T3/ORACLE/oradata/ORA9/redo*: No such file or directory

启动数据库

SQL> alter database open ;

alter database open

*

ERROR at line 1:

ORA-01589: must use RESETLOGS or NORESETLOGS option for database open

SQL>  alter database open resetlogs;

Database altered.

注意,这里必须用resetlogs,否则会错误的

SQL> alter database open noresetlogs;

alter database open noresetlogs

*

ERROR at line 1:

ORA-00313: open failed for members of log group 1 of thread 1

ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'

SQL>

Resetlogs其实就是根据控制文件让系统自动重新生成redo,如果noresetlog的话,就不会重新生成redo,缺少了文件,db自然无法启动)

SQL>  host ls /T3/ORACLE/oradata/ORA9/redo*

/T3/ORACLE/oradata/ORA9/redo01.log  /T3/ORACLE/oradata/ORA9/redo02.log  /T3/ORACLE/oradata/ORA9/redo03.log

SQL>

检验

SQL> select * from test.test;

       TEL

----------

         1

         2

         3

         4

SQL>

数据一点儿都没有丢失

结论:

如果数据库是正常关闭的,用recover database until cancel可以轻松恢复或者说重新建立所有的redo,不再区分是否是当前日志,而且由于正常关闭,不会丢失任何数据,唯一可能丢失的情况就是如果日志还没有归档

这种恢复方法 由于要resetlogs,所以在恢复完成后,日志清零,以前的备份不再起作用,所以建议立即备份

SQL> archive log list;

Database log mode              Archive Mode

Automatic archival             Enabled

Archive destination            /T3/ORACLE/arch

Oldest online log sequence     0

Next log sequence to archive   1

Current log sequence           1

SQL>

实验三:通过重新生成控制文件来恢复redo

前面的都一样,只是处理方法不一样

SQL> startup

ORACLE instance started.

Total System Global Area  353862792 bytes

Fixed Size                   730248 bytes

Variable Size             285212672 bytes

Database Buffers           67108864 bytes

Redo Buffers                 811008 bytes

Database mounted.

ORA-00313: open failed for members of log group 1 of thread 1

ORA-00312: online log 1 thread 1: '/T3/ORACLE/oradata/ORA9/redo01.log'

SQL> alter database backup controlfile to trace;

Database altered.

SQL> shutdown immediate

ORA-01109: database not open

Database dismounted.

ORACLE instance shut down.

SQL>

2、  修改一下刚才生成的那个文件

CREATE CONTROLFILE REUSE DATABASE "ORA9"  RESETLOGS  ARCHIVELOG

--  SET STANDBY TO MAXIMIZE PERFORMANCE

    MAXLOGFILES 50

    MAXLOGMEMBERS 5

    MAXDATAFILES 100

    MAXINSTANCES 1

    MAXLOGHISTORY 226

LOGFILE

  GROUP 1 '/T3/ORACLE/oradata/ORA9/redo01.log'  SIZE 100M,

  GROUP 2 '/T3/ORACLE/oradata/ORA9/redo02.log'  SIZE 100M,

  GROUP 3 '/T3/ORACLE/oradata/ORA9/redo03.log'  SIZE 100M

-- STANDBY LOGFILE

DATAFILE

  '/T3/ORACLE/oradata/ORA9/system01.dbf',

  '/T3/ORACLE/oradata/ORA9/undotbs01.dbf',

  '/T3/ORACLE/oradata/ORA9/cwmlite01.dbf',

  '/T3/ORACLE/oradata/ORA9/drsys01.dbf',

  '/T3/ORACLE/oradata/ORA9/example01.dbf',

  '/T3/ORACLE/oradata/ORA9/indx01.dbf',

  '/T3/ORACLE/oradata/ORA9/odm01.dbf',

  '/T3/ORACLE/oradata/ORA9/tools01.dbf',

  '/T3/ORACLE/oradata/ORA9/users01.dbf',

  '/T3/ORACLE/oradata/ORA9/xdb01.dbf',

  '/T3/ORACLE/oradata/ORA9/test01.dbf'

CHARACTER SET ZHS16GBK

;

另存为一个脚本,运行他

SQL> @clone.sql

Control file created.

SQL> alter database open resetlogs;

Database altered.

SQL>

搞定……………

结论:这种方法的关键是重新创建控制文件,后面的步骤和前面的道理一样的

前面的三种方法都是假设db是正常关闭的,数据已经写入数据库文件中,所以不会由数据存在redo种,所以clear的话也不会有数据丢失

 
阅读(4637) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~