eygle.com   eygle.com
eygle.com eygle
eygle.com  
 

« DBA的新年及圣诞礼物-《深入解析Oracle》 | Blog首页 | 谁与争锋-数据库管理工具OEM、I3的取舍 »

圣诞超级复杂困难之Oracle数据库大恢复
modb.pro

昨天,一个朋友公司的数据库崩溃。

这再次印证了我反复提到的一个命题:数据库也需要休息
每逢节假日,数据库也经常会自我选择放假

以前我说:年终难终 进入数据库事故多发期,一年一度今又是,记得另外一个圣诞节,我还和Biti一起在北京的时候,同样遇到一个上海的朋友数据库崩溃,我们远程指导这位朋友恢复了数据。

这次的事情是这样的。
1.首先主机宕机,磁盘出错
看到以下这类错误,一般你的数据都很危险了

Dec 24 13:52:13 kernel: sda5: rw=0, want=18298437640, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=10384710304, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=8756273744, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=5023902272, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=6730428824, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=8884660792, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=9182513808, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=5002858800, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=6730428824, limit=163846872
Dec 24 13:52:13 kernel: attempt to access beyond end of device
Dec 24 13:52:13 kernel: sda5: rw=0, want=15872410168, limit=163846872


2.数据文件大量损坏

当然这次也不例外,大量文件损坏,dbv大量如下错误:

[oracle@stat datafile]$ dbv file=o1_mf_system_29448mn7_.dbf blocksize=8192

DBVERIFY: Release 10.2.0.2.0 - Production on Thu Dec 25 22:17:52 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.

DBVERIFY - Verification starting : FILE = o1_mf_system_29448mn7_.dbf
Page 40 is influx - most likely media corrupt
Corrupt block relative dba: 0x00400028 (file 1, block 40)
Fractured block found during dbv:
Data in bad block:
type: 6 format: 2 rdba: 0x00400028
last change scn: 0x0000.18990f0e seq: 0x1 flg: 0x06
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0xbc120601
check value in block header: 0xc0cb
computed block checksum: 0xb003

Page 232 is influx - most likely media corrupt
Corrupt block relative dba: 0x004000e8 (file 1, block 232)
Fractured block found during dbv:
Data in bad block:
type: 6 format: 2 rdba: 0x004000e8
last change scn: 0x0000.18991b98 seq: 0x1 flg: 0x06
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x6c440601
check value in block header: 0x8d7f
computed block checksum: 0x77dc

3.控制文件损坏
启动数据库出现如下错误:

Wed Dec 24 17:08:52 2008
ALTER DATABASE MOUNT
Wed Dec 24 17:08:56 2008
Errors in file /opt/oracle/admin/stat/udump/stat_ora_4630.trc:
ORA-00600: internal error code, arguments: [kccpb_sanity_check_2], [11258908], [10375171], [0x0], [], [], [], []
Wed Dec 24 17:08:57 2008
ORA-600 signalled during: ALTER DATABASE MOUNT...
Wed Dec 24 17:09:01 2008
Starting ORACLE instance (normal)
Wed Dec 24 17:16:22 2008
Corrupt block 1 found during reading backup piece, file=/opt/oracle/product/db10g/dbs/snapcf_stat.f, corr_type=2

4.经过反复确认,这个环境Over了

5.不完全的备份
以前的备份机制使得我可以从远程主机找到一系列备份集,但是没有控制文件。
通过备份集、dbms_backup_restore等手段,首先恢复出来数据文件,然后尝试启动数据库

6.强制打开
通过强制resetlogs手段打开数据库,出现ORA-600 4000错误

Wed Dec 24 18:56:00 2008
Errors in file /opt/oracle/admin/stat/udump/stat_ora_21479.trc:
ORA-00600: internal error code, arguments: [4000], [15], [], [], [], [], [], []
Wed Dec 24 18:56:01 2008
Errors in file /opt/oracle/admin/stat/udump/stat_ora_21479.trc:
ORA-00704: bootstrap process failure
ORA-00704: bootstrap process failure
ORA-00600: internal error code, arguments: [4000], [15], [], [], [], [], [], []

7.通过BBED解决ORA-600 4000错误
这个没说的,只能通过BBED搞定了,修复有问题的数据块,再次尝试打开数据库


8.遇到ORA-600 2662错误

这个错误就好解决了,通过我网站上的示例就可以解决:

Wed Dec 24 21:13:17 2008
Errors in file /opt/oracle/admin/stat/udump/stat_ora_28316.trc:
ORA-00600: internal error code, arguments: [2662], [0], [412717646], [0], [412772634], [8389633], [], []
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00600: internal error code, arguments: [2662], [0], [412717644], [0], [412772634], [8389633], [], []
Wed Dec 24 21:13:18 2008
Errors in file /opt/oracle/admin/stat/udump/stat_ora_28316.trc:
ORA-00600: internal error code, arguments: [2662], [0], [412717647], [0], [412772634], [8389633], [], []
ORA-00600: internal error code, arguments: [2662], [0], [412717646], [0], [412772634], [8389633], [], []
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00600: internal error code, arguments: [2662], [0], [412717644], [0], [412772634], [8389633], [], []
Wed Dec 24 21:13:18 2008
Errors in file /opt/oracle/admin/stat/udump/stat_ora_28316.trc:
ORA-00600: internal error code, arguments: [2662], [0], [412717647], [0], [412772634], [8389633], [], []
ORA-00600: internal error code, arguments: [2662], [0], [412717646], [0], [412772634], [8389633], [], []
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00600: internal error code, arguments: [2662], [0], [412717644], [0], [412772634], [8389633], [], []


9.解决ORA-600 4097号错误

接下来继续出现ORA-600 4097号错误,这个也好解决,搞定UNDO表空间就Ok了
Wed Dec 24 21:18:12 2008
Errors in file /opt/oracle/admin/stat/bdump/stat_j000_28723.trc:
ORA-00600: internal error code, arguments: [4097], [], [], [], [], [], [], []

10.解决一些其他小问题
此处省略10000字,终于搞定了用户数据库!

这个案例所用到的所有知识在我的网站上全都有详细介绍,不过要能把所有知识综合运用才能解决这次的故障,这真是圣诞节对我的一大考验!


历史上的今天...
    >> 2018-12-25文章:
    >> 2011-12-25文章:
    >> 2010-12-25文章:
    >> 2009-12-25文章:
    >> 2007-12-25文章:
    >> 2006-12-25文章:
    >> 2005-12-25文章:
           圣诞狂购物 独自吃匹萨
    >> 2004-12-25文章:

By eygle on 2008-12-25 22:08 | Comments (25) | Backup&Recovery | Case | 2135 |

25 Comments

bbed用得好熟啊.

这么复杂啊,强的,我已经搞不定这么复杂的问题了。

最好能有详细的介绍啊,这种实际的案例对于学习和掌握实际使用技巧是很难得的!!

eygle,强烈建议分享分析问题,解决问题的完整步骤。以供学习提高。为盼

解决一下要几多米啊?1w够的不?哈哈

这个Case回头一定要细致总结出来的,不过估计要写100页不止!

关键时刻显大师功力。

真是强大!

这机器宕的够厉害!
这灾难恢复的够痛快!

我想eygle也足以能调的动大家的胃口了,言犹未尽,期待eygle的此篇大作吧。

一个Oracle的爱好者对eygle的此次恢复做个推测,希望eygle不吝赐教,而不是浅尝辄止
“一切Oracle,源于Oracle”,所谓最高的高手其实是那些了解Oracle源代码的人,而普罗万众、绝大多数的Oracle爱好者对于一些细节的钻研,掌握实际上是通过试验来验证的,即相当于软件测试的“黑盒测试”,eygle应该也不例外吧。
对于大多数oracle爱好者,metalink是最常获得资料和解决方法的地方,但普通用户的metalink帐号和Oracle公司员工能够使用的metalink帐号是不一样的,Oracle公司员工能够查到普通用户看不到的internal信息。eygle我想你虽然没在Oracle,但Oracle公司中不乏你的朋友,搞个帐号应该不是难事,虽然这是在Oracle公司明令禁止的,即使你有Oracle ACE的头衔也是如此。
ORA-600[4000] 导致数据库不能启动,往往是bootstrap$出了问题,看到eygle提到了bbed,推测eygle可能是将好库的bootstrap$涉及的块copy到有问题的库中,毕竟 bootstrap$ 占用的块很少。另外,metalink的internal文章上有很多涉及ORA-600[4000]的错误解决步骤,但用好的块去替换坏的块可能更加巧妙些。
“接下来继续出现ORA-600 4097号错误,这个也好解决,搞定UNDO表空间就Ok了”,涉及到回滚段相关的错误,希望Oracle在启动的过程中绕过回滚段的无非两个隐含参数:_offline_rollback_segments和_corrupt_rollback_segments,根据解决方法的描述,推测最后要重创新的undo表空间而删除旧的undo表空间,因此使用_corrupt_rollback_segments的可能性更大。
另外,虽然最后用特殊方法打开了库,但数据库已经处于一种不是“一致性”的状态了,推测用户属于那种只要库能起来就“万岁”的那种(国内大多数用户都是这种),不知eygle有没有提前告知此点,这属于一个support良心的范畴。

吓我,良心都抬出来了:)

不过楼上放心,这个客户是我的长期客户,他们的问题就是我的问题了。
特殊方法Open之后,exp/imp重建一般是免不了的。


另,4000错误不是bootstrap$的问题,是事务不一致的问题。metalink internal关于这些我没看过。
我受益于ZGH原来的一篇提示。

前面我提过,实际上不同错误的处理方法我都写过,关于_offline_rollback_segments等特殊参数,在Google上也到处都是,不是什么秘密。

我想请教个问题,你用了_corrupt_rollback_segments把库打开后,怎么校验数据是否出现问题,我想dsi里说的这2个导致的库不一致不是exp和imp能搞定的吧

SQL> create table test(id int) tablespace users;

表已创建。

SQL> insert into test select object_id from dba_objects;

已创建52173行。

SQL> alter system flush buffer_cache;

系统已更改。

SQL> select name from v$rollname;

NAME
------------------------------
SYSTEM
_SYSSMU1$
_SYSSMU2$
_SYSSMU3$
_SYSSMU4$
_SYSSMU5$
_SYSSMU6$
_SYSSMU7$
_SYSSMU8$
_SYSSMU9$
_SYSSMU11$

已选择11行。

SQL> create spfile from pfile='D:\a.txt';

文件已创建。

SQL> startup
ORACLE 例程已经启动。

Total System Global Area 838860800 bytes
Fixed Size 1251776 bytes
Variable Size 444597824 bytes
Database Buffers 385875968 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
数据库已经打开。
SQL> select count(*) from test;

COUNT(*)
----------
52173

SQL> show parameter corrupt

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_corrupted_rollback_segments string _SYSSMU1$, _SYSSMU2$, _SYSSMU3
$, _SYSSMU4$, _SYSSMU5$, _SYSS
MU6$, _SYSSMU7$, _SYSSMU8$, _S
YSSMU9$, _SYSSMU11$

这时候数据就出现了逻辑错误

SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> create spfile from pfile='D:\a.txt';

文件已创建。

SQL> startup
ORACLE 例程已经启动。

Total System Global Area 838860800 bytes
Fixed Size 1251776 bytes
Variable Size 444597824 bytes
Database Buffers 385875968 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
数据库已经打开。
SQL> show parameter corrupt

NAME TYPE VALUE
------------------------------------ ----------- -------------------------
_corrupted_rollback_segments string
SQL> select count(*) from test;

COUNT(*)
----------
0

在这种情况下,不可能只通过数据库/DBA的手段就完全解决问题的。

一定还需要业务人员的介入,去检查数据,手工修正。
丢失redo 、 archive log已经肯定会损失一致性,不能期望万无一失了。

你提到的状况也的确不是数据库层面能简单处理的。

不过,退一步,如果真是非常重要的金融、电信等数据库一般也不会处于这样的境地的。

还有一个问题要请教下,看了logzgh那篇文章,有个疑惑,itl的flag显示的是2001,这说明,事务已经提交了啊,只是还没有做块清除,根据那文件里说的

在600号的Trace文件中有:

ORA-00600: internal error code, arguments: [4000], [46], [], [], [], [], [], []
Current SQL statement for this session:
select ctime, mtime, stime from obj$ where obj# = :1

这时候查询为什么还要去读回滚段啊

还有一个问题要请教下,看了logzgh那篇文章,有个疑惑,itl的flag显示的是2001,这说明,事务已经提交了啊,
根据那文件里说的

在600号的Trace文件中有:

ORA-00600: internal error code, arguments: [4000], [46], [], [], [], [], [], []
Current SQL statement for this session:
select ctime, mtime, stime from obj$ where obj# = :1

这时候查询为什么还要去读回滚段啊

还有一个问题要请教下,看了logzgh那篇文章,有个疑惑,itl的flag显示的是2001,这说明,事务已经提交了啊
根据那文件里说的

在600号的Trace文件中有:

ORA-00600: internal error code, arguments: [4000], [46], [], [], [], [], [], []
Current SQL statement for this session:
select ctime, mtime, stime from obj$ where obj# = :1

这时候查询为什么还要去读回滚段啊

刚才提示提交失败,怎么提交了2次

Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x002e.025.00005b2c 0x00800f78.080c.01 --U- 1 fsc 0x0000.c5b527cf

这里的U指Upper Bound commit,其参考的Control SCN也是记录在UNDO Header上的,所以在Cleanout时也是要读UNDO的。

btw:4000错误并不是每次修改这个内容都能生效,我还遇到一次和这次不同的情况。

这里的U指Upper Bound commit ,不一定是control scn吧,如果事务的slot还没被重用的的话,得到的也是准确的commit scn,U应该是说明做过块清除了吧,而且这样的情况应该也不会存在查询的scn小于块的scn,只里应该是没必要读undo了

--U- Flag是否做过Cleaned Out应该结合lck位来看

如果lck位=0,则说明是依据Upper Bound Comitt做cleaned out
如果lck > 0, SCN仍然是FSC.Scnbase,则说明仍然需要做cleand out的。

很耐心的看完了楼上高人的讨论

能否记录更详细些,期待中。

最好提供详细步骤,让大家学习学习


CopyRight © 2004~2020 云和恩墨,成就未来!, All rights reserved.
数据恢复·紧急救援·性能优化 云和恩墨 24x7 热线电话:400-600-8755 业务咨询:010-59007017-7040 or 7037 业务合作: marketing@enmotech.com