ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 一次无备份、非归档数据库断电恢复的全过程

一次无备份、非归档数据库断电恢复的全过程

原创 Linux操作系统 作者:victorymoshui 时间:2011-06-09 21:53:13 0 删除 编辑
环境:Windows 2000 Advanced Server sp4+Oracle 9206

现象描述:客户数据库机房在清理过程中,清洁人员不小心将服务器后面的电源线直接拔掉,导致实例断电,数据库无法启动。数据库运行在非归档模式下,没有备份,只有前一天晚上的全库导出文件。数据库重新启动以后,数据库无法打开,用SQLPLUS连接,无论如何都无法登录进去,报错如下:

SQL> conn/as sysdba
ERROR:
ORA-01041: internal error. hostdef extension doesn't exist??

SQL> conn sys/aa as sysdba
ERROR:
ORA-03113: end-of-file on communication channel

解决问题的第一步就是查询alert log,相应内容如下:
代码:

Mon Aug 01 22
:03:52 2005
alter database mount exclusive
Mon Aug 01 22
:03:
56 2005
Successful mount of redo thread 1
,
with mount id 1487340872
Mon Aug 01 22
:03:
56 2005
Database mounted in Exclusive Mode
. Completed: alter database mount exclusive
Mon Aug 01 22
:03:
56 2005
alter database open
Mon Aug 01 22
:03:
56 2005
Beginning crash recovery of 1 threads
Mon Aug 01 22
:03:
56 2005
Started redo scan
Mon Aug 01 22
:03:
56 2005
Completed redo scan
17289 redo blocks read
,
394 data blocks need recovery
Mon Aug 01 22
:03:
56 2005
Started recovery at
Thread 1
: logseq 52, block 92832,
scn 0.0
Mon Aug 01 22
:03:
56 2005
Recovery of Online Redo Log
:
Thread 1 Group 1 Seq 52 Reading mem 0
Mem
# 0 errs 0: E:/ORACLE/ORADATA/RMADB/REDO01.LOG *** Corrupt block relative dba: 0x02c1f8c8 (file 11, block 129224) Fractured block found during crash/instance recovery
Data in bad block
-
type: 6 format: 2 rdba:
0x02c1f8c8
last change scn
: 0x0000.0017d929 seq: 0x1 flg:
0x06
consistency value in tail
:
0xc0250601
check value in block header
: 0x54b9, computed block checksum:
0x190c
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x02c1f8c8 (file 11, block 129224) found same corrupted data *** Corrupt block relative dba: 0x008008f9 (file 2, block 2297) Fractured block found during crash/instance recovery
Data in bad block
-
type: 2 format: 2 rdba:
0x008008f9
last change scn
: 0x0000.0017f574 seq: 0x2 flg:
0x04
consistency value in tail
:
0x1c9c0208
check value in block header
: 0xaede, computed block checksum:
0xd131
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x008008f9 (file 2, block 2297) found same corrupted data *** Corrupt block relative dba: 0x02c0d2a8 (file 11, block 53928) Fractured block found during crash/instance recovery
Data in bad block
-
type: 6 format: 2 rdba:
0x02c0d2a8
last change scn
: 0x0000.0017fbcb seq: 0x1 flg:
0x06
consistency value in tail
:
0xd0270601
check value in block header
: 0x9225, computed block checksum:
0x2bec
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x02c0d2a8 (file 11, block 53928) found same corrupted data *** Corrupt block relative dba: 0x02c09248 (file 11, block 37448) Fractured block found during crash/instance recovery
Data in bad block
-
type: 6 format: 2 rdba:
0x02c09248
last change scn
: 0x0000.0017fa10 seq: 0x1 flg:
0x06
consistency value in tail
:
0xf7ec0601
check value in block header
: 0xd53f, computed block checksum:
0xdfc
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x02c09248 (file 11, block 37448) found same corrupted data *** Corrupt block relative dba: 0x028205c3 (file 10, block 132547) Fractured block found during crash/instance recovery
Data in bad block
-
type: 6 format: 2 rdba:
0x028205c3
last change scn
: 0x0000.0017e7ca seq: 0x1 flg:
0x06
consistency value in tail
:
0xf0270601
check value in block header
: 0x3e5e, computed block checksum:
0x17ed
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x028205c3 (file 10, block 132547) found same corrupted data *** Corrupt block relative dba: 0x00800099 (file 2, block 153) Fractured block found during crash/instance recovery
Data in bad block
-
type: 38 format: 2 rdba:
0x00800099
last change scn
: 0x0000.0017feda seq: 0x1 flg:
0x04
consistency value in tail
:
0xe6532601
check value in block header
: 0x2901, computed block checksum:
0x2c6
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x00800099 (file 2, block 153) found same corrupted data *** Corrupt block relative dba: 0x00800419 (file 2, block 1049) Fractured block found during crash/instance recovery
Data in bad block
-
type: 2 format: 2 rdba:
0x00800419
last change scn
: 0x0000.0017e682 seq: 0x3 flg:
0x04
consistency value in tail
:
0x99d90208
check value in block header
: 0x1f63, computed block checksum:
0x637
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x00800419 (file 2, block 1049) found same corrupted data *** Corrupt block relative dba: 0x00800079 (file 2, block 121) Fractured block found during crash/instance recovery
Data in bad block
-
type: 38 format: 2 rdba:
0x00800079
last change scn
: 0x0000.0017e683 seq: 0x1 flg:
0x04
consistency value in tail
:
0xfc202601
check value in block header
: 0xa5d7, computed block checksum:
0x9c09
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x00800079 (file 2, block 121) found same corrupted data *** Corrupt block relative dba: 0x00800009 (file 2, block 9) Fractured block found during crash/instance recovery
Data in bad block
-
type: 38 format: 2 rdba:
0x00800009
last change scn
: 0x0000.0017ce51 seq: 0x1 flg:
0x04
consistency value in tail
:
0xe63a2601
check value in block header
: 0x28a7, computed block checksum:
0x2f8c
spare1
: 0x0, spare2: 0x0, spare3:
0x0 *** Reread of rdba: 0x00800009 (file 2, block 9) found same corrupted data
Mon Aug 01 22
:03:
58 2005
Errors in file e
:/oracle/admin/rmadb/udumps/rmadb_ora_1664.trc
: ORA-00600: ??????, ??: [6101], [0], [15], [0], [], [], [], [] Mon Aug 01 22:03:59 2005
Errors in file e
:/oracle/admin/rmadb/udump/rmadb_ora_1664.trc
: ORA-01578: ORACLE ?????? (???? 10, ???? 41861) ORA-01110: ??? 10: 'D:/DATA/BASERINDEX_1.DAT' ORA-10564: tablespace RINDEX
ORA
-01110: ??? 10:
'D:/DATA/BASERINDEX_1.DAT' ORA-10561: block type 'TRANSACTION MANAGED INDEX BLOCK', data object# 29492 ORA-00600: ??????, ??: [6101], [0], [15], [0], [], [], [], []

...




查询Metalink中关于ora-600[6101]的错误解释,结合alert log里面的信息,我们可以知道由于断电导致数据库UNDO表空间和应用索引表空间RINDEX对应的两个数据文件损毁,产生坏块,因此数据库无法打开。值得庆幸的是,损毁的表空间不是应用数据表空间,这样至少业务数据不会有多大丢失。了解了情况以后,大抵对策也就出来了,将损毁的索引表空间对应两个数据文件offline drop,然后再通过添加隐藏参数的办法使数据库跳过回滚段的检查来不一致打开数据库。打开数据库后,再做一个全库的导出,然后重建数据库,导入数据即可。


可是这时候SQLPLUS却是始终无法登录,无论怎样连接,都是持续地报ORA-01041和ORA-03113这两个错误。尝试重配监听,通过网络连接,无法登录;用RMAN连接,还是无法登录,报的错一模一样。查询Google和Metalink,找不到有用的信息。如果连SQLPLUS都无法登录,那么恢复根本无从谈起。这时候便从各方面寻找原因,本来是想用oradim重新编辑Oracle服务,使得Windows服务启动时Instance不直接mount数据库和打开数据库。但是转而一想,目前Oracle服务还是可以自动mount数据库,只是由于数据坏块的产生无法打开数据库罢了,况且这时候只是SQLPLUS无法登录,如果手工编辑服务,数据库连mount都无法mount的话,SQLPLUS又是无法登录,那么更加难以着手进行恢复了。到这个时候只能怀疑是否是Oracle本身的问题,SQLPLUS程序因为断电的原因发生错误?

想到这一点以后,便保护好现场,重新安装Oracle并手工创建服务,再尝试进行恢复。于是便又开始了重新安装Oracle及打Patch的过程。当安装好Oracle以后,利用oradim手工编辑Oracle服务,并利用orapwd创建好相应的密码文件后,再进一步尝试恢复。这次Oracle服务启动以后,不会再启动Instance了,马上利用SQLPLUS尝试登录,乖乖,终于登录进去了:

SQL> conn/as sysdba
Connected to an idle instance.

马上尝试着启动Insance,并mount数据库,都顺利完成了:

SQL> startup nomount
ORACLE instance started.

Total System Global Area 68229684 bytes
Fixed Size 453172 bytes
Variable Size 41943040 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes

SQL> alter database mount;

Database altered.

当尝试打开数据库时,SQLPLUS马上断开连接,并重新报ORA-01041的错误:

SQL> alter database open;
ERROR:
ORA-01041: internal error. hostdef extension doesn't exist?

至此,大抵明白了刚开始时SQLPLUS为何无法登录的原因:Oracle服务成功mount数据库后,会尝试打开数据库,由于Ora-600的存在,这时候无论通过何种方式都是无法连接到数据库的,并且会报ORA-01041的错误。清楚这一点以后,我们再次尝试进一步的恢复,由于SQLPLUS无法连接,手工将Oracle服务关闭并再次打开,这时候SQLPLUS又可以登录了,于是mount数据库,创建pfile文件,准备添加隐藏参数:

SQL> create pfile='d:/init.ora' from spfile;

File created.

打开d:/init.ora文件,修改undo_management为manual,将在在里面添加如下一行隐藏参数,以便数据库打开时跳过已损坏的回滚段的检查:

*._corrupted_rollback_segments=(“_SYSSMU1$”,”_SYSSMU2$”,”_SYSSMU3$”,”_SYSSMU3$”,”_SYSSMU4$”,”_SYSSMU5$”,” _SYSSMU6$”,”_SYSSMU7$”,” _SYSSMU8$”,”_SYSSMU9$”,”_SYSSMU10$”);

这里就又带来一个问题,自从9i Undo管理方式采用自动管理以后,我们根本无法得知Oracle内部创建了几个回滚段以及回滚段相应的名称,数据库在mount状态下,我们也无法通过数据字典来查询回滚段的相应信息,那么这些回滚段的名称如何得来?如果建库以来的alert log都存在的话,那么我们可以结合创建数据库时的alert log内容以及最后一次成功打开数据库后的alert log内容来猜测数据库中回滚段的数目及名称。我们首先来查看一个alert log里面记录的创建数据库时对应创建UNDO表空间及Undo Segment的名称的例子:

代码:

Tue May 31 22
:42:26 2005
CREATE UNDO TABLESPACE UNDO DATAFILE
'd:oracleoradatademoundo01.dbf'
size 300M

Tue May 31 22
:42:
28 2005
Created Undo Segment _SYSSMU1
$ Created Undo Segment _SYSSMU2$ Created Undo Segment _SYSSMU3$ Created Undo Segment _SYSSMU4$ Created Undo Segment _SYSSMU5$ Created Undo Segment _SYSSMU6$ Created Undo Segment _SYSSMU7$ Created Undo Segment _SYSSMU8$ Created Undo Segment _SYSSMU9$ Created Undo Segment _SYSSMU10$
...



通常情况下,Oralce初始建库时都是创建10个回滚段,名称分别命名为“_SYSSMU1$”、“_SYSSMU2$”……“_SYSSMU10$”;在这里我们不难看出Undo Segment的命名规范,为“_SYSSMUn$”,其中n为Undo Segment对应的数目编号。结合最后一次数据库成功启动后的alert log里面Undo Segment的相应信息:

代码:

Sat Jul 30 10
:35:16 2005
ARC0
:
Media recovery disabled
Sat Jul 30 10
:35:
17 2005
Undo Segment 1 Onlined
Undo Segment 2 Onlined
Undo Segment 3 Onlined
Undo Segment 4 Onlined
Undo Segment 5 Onlined
Undo Segment 6 Onlined
Undo Segment 7 Onlined
Undo Segment 8 Onlined
Undo Segment 9 Onlined
Undo Segment 10 Onlined
Successfully onlined Undo Tablespace 1.
Sat Jul 30 10
:35:
17 2005
...



我们就可以得知数据库大概有几个Undo Segment以及他们对应的名称。事实上,数据库在运行过程中可能也会创建相应的Undo Segment,这些我们都可以通过alert log里面记录的内容进行补充添加,这样我们就可以知道Undo Segment的相应信息了。

添加隐藏参数后,关闭数据库服务,以刚创建的pfile进行启动:

SQL> startup nomount pfile='d:/init.ora'
ORACLE instance started.

Total System Global Area 68229684 bytes
Fixed Size 453172 bytes
Variable Size 41943040 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes

SQL> alter database mount;

Database altered.

Mount完数据库后,将损坏的索引表空间对应的数据文件offline drop掉:

SQL> alter database datafile 10 offline drop;

Database altered.

SQL> alter database datafile 11 offline drop;

Database altered.

接下便是最关键的一步,尝试打开数据库:

SQL> alter database open;

Database altered.

乖乖,数据库终于成功打开了,几个小时的折腾终于有了结果。接下来的第一步便是马上做一个全库导出。事实上当时在这个损毁的数据库上导出时应用数据表空间还是存在坏块的,一些表是无法成功导出的。但是万幸的是,这些表都是一些代码表,涉及到业务交易数据的几张重要的表都成功导出了。导出完以后,重建数据库,导入刚才全库导出的数据。结合前天晚上的全库导出文件及上面导出的日志,将损坏的数据表也完整地导入到新创建的数据库中,这样实现了数据的零丢失。至此,整个数据库的恢复顺利完成。

后记:
当时在恢复过程中为了保险起见,没有采用一些更简便的方法。事实上从后面的恢复过程中我们不难看出,最简便保险的方法就是手工编辑Oracle服务,便得Oracle服务不会自动启动数据库,这样SQLPLUS就可以登录,也就能进行后面的恢复步骤了。当时经与同事讨论以及后面的论坛交流后,发生ORA-01041这样的情况,事实上只要在Windows的任务管理器中将oracle.exe的进程kill掉,那么再次登录SQLPLUS时就可以登录了,恢复过程也就大同小异了。当时之所以选择案例中解决的办法,主要是由于前面所述两种方法在当时看来都不是十分保险,因为服务都已经成功mount数据库了,但是就是SQLPLUS无法登录。如果按上面的方法进行解决,SQLPLUS还是无法登录的话,那么根本无从谈起恢复,尤其像后面的将oracle.exe进程结束掉,又怕将本来完好的控制文件给损毁掉,这时SQLPLUS又无法登录,想重新创建都无法创建。基于这点考虑,最后才选择了案例中的恢复办法。这个案例的重点是解决SQLPLUS无法登录的问题,上面的解决办法及思路可供大家日后测试和恢复时作为参考。这里需要再次强调的是生产数据库一定要做好备份的工作,否则发生异常的话,有些情况下是根本无法完好恢复的。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9390331/viewspace-697529/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2009-08-26

  • 博文量
    173
  • 访问量
    303307