损坏回滚数据文件的恢复方法
回滚段表空间中的一个数据文件丢失或者损坏导致数据库无法识别它,在启动数据库的时候会出现ORA-1157, ORA-1110的错误,或者操作系统级别的错误,例如ORA-7360。
在关闭数据库的时候(normal或者immediate)会出现ORA-1116, ORA-1110的错误,或者操作系统级别的错误,例如ORA-7368。
感谢coolyl的辛勤工作,关于回滚段的大部分内容都是摘自他在itpub的文章。
1.损坏数据文件,但数据库处于Open状态
如果你发现有回滚段的数据文件丢失或者损坏了,而此时的数据库是处于打开的状态下并且在运行,就千万不要关闭数据库了,因为在大多数的情况下打开的时候比关闭的时候好解决问题一些。
一般也是存在有两种情况:
A、offline丢失或损坏的数据文件,然后从一个备份中恢复,执行介质恢复以保持一致性。但是这种情况要求数据库是归档方式下才可以采用的。
B、offline那个存在丢失或损坏的数据文件所在的整个回滚段表空间,然后删除整个回滚段表空间并重建,但是你必须要杀掉那些在回滚段中已经激活的用户进程才可以offline的。
通常第一种情况就比较简单实现,但是更多的用户事务将会出错并且回滚。
A的具体步骤:
1、offline丢失或损坏的数据文件
SQL> ALTER DATABASE DATAFILE '<full_path_file_name>' OFFLINE;
2、从一个有效的备份中恢复
3、执行以下查询
SELECT V1.GROUP#, MEMBER, SEQUENCE#
FROM V$LOG V1, V$LOGFILE V2
WHERE V1.GROUP# = V2.GROUP#;
这个将列出你的所有redolog文件以及它们所代表的sequence numbers
4、恢复数据文件
SQL> RECOVER DATAFILE '<full_path_file_name>';
5、确信你应用了所有的redolog文件,直至出现提示信息“Media recovery complete”
6、online那个数据文件
SQL> ALTER DATABASE DATAFILE '<full_path_file_name>' ONLINE;
B的具体步骤:
1、offline存在丢失或损坏的数据文件的回滚段表空间中的所有回滚段
SQL> ALTER ROLLBACK SEGMENT '<rollback_segment>' OFFLINE;
2、检测当然回滚段的状态
SELECT SEGMENT_NAME, STATUS FROM DBA_ROLLBACK_SEGS
WHERE TABLESPACE_NAME = '<TABLESPACE_NAME>';
3、删除所有offline的回滚段
SQL> DROP ROLLBACK SEGMENT <rollback_segment>;
4、处理那些online状态的回滚段
重新执行第二步的查询
SELECT SEGMENT_NAME, STATUS FROM DBA_ROLLBACK_SEGS
WHERE TABLESPACE_NAME = '<TABLESPACE_NAME>';
如果你已经执行过offline操作的回滚段状态仍然是online,则说明这个回滚段内有活动的事务。
你要接着查询
SELECT SEGMENT_NAME, XACTS ACTIVE_TX, V.STATUS
FROM V$ROLLSTAT V, DBA_ROLLBACK_SEGS
WHERE TABLESPACE_NAME = '<TABLESPACE_NAME>' AND SEGMENT_ID = USN;
如果没有返回结果,则证明存在丢失或损坏的数据文件的回滚段表空间中的所有回滚段都已经被offline了,然后重新执行第2步,第3步。
如果查询有结果返回,则状态应该是“PENDING OFFLINE”,接着查看ACTIVE_TX列,如果值为0,则表明此回滚段中已经没有未处理的事务了,很快就会被offline的,然后等它offline后重新执行2,3步后跳至第6步;如果值大于0,则继续到第五步。
5、强制那些包含活动事务的回滚段offline
活动的事务应该被提交或者回滚,执行下面的查询看看哪些用户占用了回滚段:
SELECT S.SID, S.SERIAL#, S.USERNAME, R.NAME "ROLLBACK"
FROM V$SESSION S, V$TRANSACTION T, V$ROLLNAME R
WHERE R.NAME IN ('<PENDING_ROLLBACK_1>', ... , '<PENDING_ROLLBACK_N>')
AND S.TADDR = T.ADDR AND T.XIDUSN = R.USN;
最好能直接联系到那些user让他们自己去回滚或者提交事务,如果不能做到的话,那就只能强制性的杀掉进程了。
ALTER SYSTEM KILL SESSION '<SID>, <SERIAL#>';
杀掉进程后再过一段时间后回滚段会自动清除那些事务,然后就可以回到第二步继续查询了。
6、删除回滚段
SQL> DROP TABLESPACE <tablespace_name> INCLUDING CONTENTS;
7、重建回滚段并online它们
说明:
1、数据库如果是open状态,就可以直接在open状态下解决问题,没有必要停下数据库,增加down机时间
2、不管上上面那种恢复方法都是正常性的恢复,不会引起数据的不一致或错误。
2.数据库关闭,但是数据文件中没有活动事务
这种情况下最简单的方法就是offline drop掉这个坏了的或者丢失的数据文件,然后以restricted模式打开数据库然后删除并且重建包含损坏文件的回滚段表空间。
具体步骤如下:
1、确定数据库是正常的关闭的。方法是可以去查看alert文件,到最后看是否有如下信息:
alter database dismount
Completed: alter database dismount
如果有的话,就证明数据库是正常关闭的,否则就不能用这个方法去恢复。
2、修改init参数文件,移去ROLLBACK_SEGMENTS中包含的损坏数据文件的回滚段表空间的回滚段
如果你不能确定哪些回滚段是坏的,简单的方法是你可以注释掉整个ROLLBACK_SEGMENTS
3、以restricted模式去mount数据库
SQL> STARTUP RESTRICT MOUNT;
4、offline drop掉那个坏的数据文件
SQL> ALTER DATABASE DATAFILE '<full_path_file_name>' OFFLINE DROP;
5、打开数据库
SQL> ALTER DATABASE OPEN;
如果你看到如下信息“Statement processed”,则跳到第7步,如果你看到ORA-604, ORA-376, and ORA-1110的错误信息,继续第6步。
6、正常的关闭数据库,然后在init文件中注释掉ROLLBACK_SEGMENTS,并加入隐含参数
_corrupted_rollback_segments = ( <rollback1>,...., <rollbackN> )
然后以restricted模式打开数据库
SQL> STARTUP RESTRICT
7、删除掉那个包含损坏文件的回滚段表空间
DROP TABLESPACE <tablespace_name> INCLUDING CONTENTS;
8、重建回滚段表空间,记得创建后要把回滚段都online
9、重新使数据库对所有用户可用
SQL> ALTER SYSTEM DISABLE RESTRICTED SESSION;
10、然后正常关闭数据库,修改init文件
如果开始只是注释掉了ROLLBACK_SEGMENTS的,就去掉注释即可,如果加了隐含参数的,注释掉它,并在ROLLBACK_SEGMENTS加入所有的回滚段。
11、正常启动数据库
SQL> Startup;
说明:
1、这种方法的前提条件是数据库是正常关闭(不是abort)可用
2、这种方法是正常方法,不会引起数据错误
3.数据库关闭,数据文件中有活动事务,没有可用备份
一般造成这种原因的情况是采用了shutdown abort或其它原因异常关机(如断电)导致的
1、开启一个事务
SQL> set transaction use rollback segment rbs0;
Transaction set.
SQL> insert into test (a) values (1);
1 row created.
2、异常关闭
SQL> shutdown abort;
ORACLE instance shut down.
3、删除rbs的一个数据文件
C:>del D:\oracle\oradata\dodo\UNDOTBS01.DBF
4、修改INIT<sid>.ora
rollback_segments=(system)
添加_corrupted_rollback_segments=(rbs0,rbs1,rbs2……)
5、SQL>Startup mount
6、Drop掉表空间
SQL>alter database datafile 'D:\oracle\oradata\dodo\UNDOTBS01.DBF' offline drop;
Database altered.
7、SQL>recover database;
8、SQL>alter database open;
Database altered.
9、SQL>select * from v$rollname;
USN NAME
---------- ------------------------------
0 SYSTEM
10、SQL>select segment_name,tablespace_name,status from dba_rollback_segs;
SEGMENT_NAME TABLESPACE_NAME STATUS
------------------------------ ------------------------------ ----------------
SYSTEM SYSTEM ONLINE
RBS0 RBS NEEDS RECOVERY
RBS1 RBS NEEDS RECOVERY
RBS2 RBS NEEDS RECOVERY
11、Drop segment
SQL>drop rollback segment rbs0;
重算段已丢弃。
SQL>drop rollback segment rbs1;
重算段已丢弃。
SQL>drop rollback segment rbs2;
重算段已丢弃。
12、SQL>select segment_name,tablespace_name,status from dba_rollback_segs;
SEGMENT_NAME TABLESPACE_NAME STATUS
------------------------------ ------------------------------ ----------------
SYSTEM SYSTEM ONLINE
13、SQL>drop tablespace rbs including contents;
表空间已丢弃。
14、重建新的回滚表空间及回滚段,并联机。
15、SQL>shutdown abort
16、再修改INIT<sid>.ora
rollback_segments=(rbs0,rbs1,rbs2)
将_corrupted_rollback_segments=(rbs0,rbs1,rbs2)去掉
17、SQL>startup
说明:
1、这种办法是万不得以的时候使用的方法,如果有备份,都建议从备份上进行恢复
2、这种方法恢复的数据库,可能会引起数据库的数据错误
3、恢复成功以后,建议exp/imp数据,并重新分析检查数据库
4.数据库关闭,数据文件中有活动事务,从备份恢复
1、从一个有效的备份中恢复损坏的数据文件
2、mount数据库
3、执行以下查询
SELECT FILE#, NAME, STATUS FROM V$DATAFILE;
如果发现要恢复的文件是offline状态的话,要先online它:
ALTER DATABASE DATAFILE '<full_path_file_name>' ONLINE;
4、执行以下查询
SELECT V1.GROUP#, MEMBER, SEQUENCE#, FIRST_CHANGE#
FROM V$LOG V1, V$LOGFILE V2
WHERE V1.GROUP# = V2.GROUP# ;
这个将列出redlog文件所代表的sequence和first change numbers
5、如果数据库是非归档情况下,执行以下查询:
SELECT FILE#, CHANGE# FROM V$RECOVER_FILE;
如果CHANGE#大于最小的redolog文件的FIRST_CHANGE#,则数据文件可以被恢复,记得在应用日志的时候要把所有redolog文件全部应用一遍。
如果CHANGE#小于最小的redolog文件的FIRST_CHANGE#,则数据文件就不可以被恢复了,这时候你要从一个有效的全备份中去恢复数据库了,如果没有全备份的话,那你就只能把数据库强制打开到一个不一致的状态去exp出数据,然后重新建库导入数据,因为这种方式的恢复oracle是不推荐用户自己做的,所以这里我就不详细说明了。
6、恢复数据文件
RECOVER DATAFILE '<full_path_file_name>' ;
7、确信你应用了所有的redolog文件,直至出现提示信息“Media recovery complete”
8、打开数据库
说明:
1、这种方法要求在归档有备份的方式下进行,而且是建议方式
2、这种方法不会导致数据库的错误
-The End-