« DBA的新年及圣诞礼物-《深入解析Oracle》 | Blog首页 | 谁与争锋-数据库管理工具OEM、I3的取舍 »
圣诞超级复杂困难之Oracle数据库大恢复
链接:https://www.eygle.com/archives/2008/12/difficult_recovery_christmas.html
昨天,一个朋友公司的数据库崩溃。
这再次印证了我反复提到的一个命题:数据库也需要休息。
每逢节假日,数据库也经常会自我选择放假。
以前我说:年终难终 进入数据库事故多发期,一年一度今又是,记得另外一个圣诞节,我还和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=8192DBVERIFY: 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: 0xb003Page 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 |
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的。
很耐心的看完了楼上高人的讨论
能否记录更详细些,期待中。
最好提供详细步骤,让大家学习学习