Oracle 11gR2 for Windows遭遇ora-600[4194]的恢复案例

某客户的数据库出现异常,非归档环境。Instance crash之后正常open,然而数据库很快就crash 掉。我们来简单分析一下:

上面的错误对于大家来讲或许并不陌生,ora-00600 [4194]是一个非常常见的错误。然而,细心的人或许注意到了,
这里有一点不同的是:[4194]后面的2位都是空的。

对于ora-00600 [4194] 错误,Oracle MOS文档有个标准的解释,如下:

简单的讲,就是Oracle SMON进程在进程事务rollback时,发现redo block中对应的undo record 编号和
undo block中的undo record 编号不一致,进而导致事务无法进行正常回滚,最后抛出这个错误。

我们来看下smon 进程的trace,里面提到了异常的事务信息:

UBA应该是:0x00c000e9.0x12bf.0x25,即:0x00c000e9.12bf.25,这里的XID为:xid:  0x0006.010.000033dd

说明是第对应的第16个事务槽(SLOT:0x10). record 编号为0x25。 opcode为5.7,标示Begin transaction (transaction table update)
那么我们定位到这个record(0x25),来看看undo block的实际dump是什么:

我们可以看到该事务(0x10)回滚到0x25就结束了,因为rci值为0,说明这里就是结束的位置。 大家注意看这里的opcode代码,layer为11,opc为1.
那么也就是说undo block这个record实际上的opcode为:11.1.

大家应该都知道11.1标示什么?  11.1 标示:Interpret Undo Record (Undo)。同时看下面的信息也可以知道这里应该是进行了update操作。(URP)。

因此,很明显redo和undo block(file 3 block 233)的信息是不一致的。
上面的信息不够完整,下面我将recover失败的block(file 3 block 233)的信息贴出来:

我们可以看到,最新的一个事务事务XID为:0x0006.002.000033d9。seq为seq: 0x12bf 整个undo block 一共包含cnt: 0x3b(即59)个undo record记录;其中 irb: 0x3b 标示最新的一个事务
如果进行rollback,那么第0x3b的事务将是rollback的起点。

那么一个事务进行rollback,到什么时候结束呢? 当对应的rci值为0时,即表示结束。很明显,最新的事务的SLOT为0x002。而出问题的事务的slot是0x010(转换为10进制为16)。

当然,最后要处理这个case是比较容易的,通过屏蔽第6号回滚段即可,这里不在累述。

 

 

Windows环境Oracle数据文件大小变成0的恢复案例

某客户的Oracle数据库部署在windows环境上,可能是由于存储问题或者windows本身文件系统的问题,进而出现IO问题,最后数据库重启之后,竟然无法启动了,报错无法读取其中的几个文件,alert log如下:

我们可以看到,重启之前Oracle就开始报ORA-00700,ORA-00600以及ORA-48102错误。重启之后的错误更是郁闷,如下:

很明显这是文件异常了,从操作系统查看,发现这4个文件大小居然为0了。 这显然是不正常的。 实际上我检查发现还有另外2个文件也是有问题,
可能是文件头损坏了,通过dbv校验直接报错。

最后经过处理之后,成功帮客户抢救了数据,据说最后只是发现某个核心表丢了一点数据,损失不大。

不推荐使用windows来跑Oracle,感觉总是会有一些莫名其妙的问题发生,而且很难搞。还有,数据库一定要归档模式,定期物理备份,否则一旦出现故障,就是灾难性的。

 

 

某客户ERP系统Oracle 8.0.5 数据库恢复案例

某客户的ERP数据库出现异常,数据库版本比较老,是Oracle 8.0.5。 问题本身并不复杂,简单记录一下。

主要的问题是客户的应用访问报错,通过分析客户传的alert log发现出现了大量的IO错误,如下:

从alert log 来看,上述报错的文件出现IO error,实际上该文件是确实存在的。开始我以为有可能是数据文件头的
os block 损坏了,通过dd dump分析发现是OK,如下:

同时,从报错来看,提到了一个block,查看trace可以看到该block的内容如下:

上述的dump内容非常简单。我们回头来看下前面的错误:

Error 1115 encountered while recovering transaction (28, 23)

首先我们需要明白,这里的28,,23分别代表什么含义 ?

正常情况下,这里的28表示回滚段编号,23表示事务槽编号。 通过检查发现实际上这里的信息是不对的。
客户的系统中根本不存在这个回滚段。通过block号,我们定位到实际上是第4号回滚段。

因此要解决这个回滚段事务的问题,就很简单了,通过_corrupted_rollback_segments=RBS4 然后强制drop即可。

另外,由于这里事务涉及的操作,其实是针对Index的操作,因此。我们drop完成之后,还需要重建相关的Index。

当处理完这个之后,客户反馈另外一个数据文件也有问题,当操作某个表时,会出现异常,如下:

实际上,这个表,在我处理之前,直接count(1)操作,都会报上面的错误。经查,这是Oracle 805的bug导致。

通过调整disk_async_io=false,以及db_file_multiblock_read_count为16,解决了这个问题。

虽然可以进行count,然而客户反馈业务操作仍然报错。最后我们发现,这可能是oracle 805的bug导致,当数据文件大小
超过2GB时,会出现异常。实际上,我在进行dbv检查时,该数据文件都会报错。

最后我们通过cats重建表,然后重建index解决了该问题。

备注:805版本中,rename table语法很坑爹,必须这样:

alter table roger.test rename to test_new;

这个系统将近20年了,也正是够老的了。

ORA-15196: invalid ASM block header [kfc.c:26076] [hard_kfbh] 恢复案例

这是某个网友的数据库,11g ASM环境. 其中ASM元数据出现损坏,导致DiskGroup无法mount。不过比较万幸的存储有镜像。即使是这样,据说存储工程师恢复也花了1天多,对于我们的业务系统来讲,这是不可接受的。
我这里将该数据库case的信息贴出来,供大家参考!(备注:我们提供完善的数据库各种解决方案,详情请看:云和恩墨)

从上述错误我们可以判断,ASM DISKGROUP无法mount。报错的原因是如下:

从这几行信息来看,DATAVG磁盘组的第27号盘的第0个AU的第1号block损坏了。 实际上,这就是disk header损坏了。

下面针对ORA-15196错误进行简单解释:

ORA-15196: invalid ASM block header [kfc.c:26076] [hard_kfbh] [2147483675] [1] [0 != 130]

[kfc.c:26076]: 表示运行kfc.c代码的第26076行出现问题
[hard_kfbh]:    表示检查失败的类型
[2147483675]:  表示file number
[1]:           表示block number
[0 != 130]:     表示该处的值,当前是0,检测发现实际上应该是130才对.

实际上,对于这样的错误,一旦出现,ASM元数据损坏的不仅仅是磁盘头。经过我们判断,至少前面4M的ASM元数据都已经
损坏。对于这样的情况,可能使用AMDU是无法进行数据文件的抽取的。

一般来讲,对于是external的DiskGroup,前面42M的ASM元数据如果不是彻底损坏,那么DiskGroup中的数据都是比较容易弄出来的。

如果损坏非常严重,那么可能只能使用数据库抽取工具进行扫盘。目前DUL或ODU都可以完美的解决这样的情况。

如果你遇到类似的数据库故障,那么请第一时间联系我们!

某客户的一套5TB Oracle RAC 数据库恢复案例

某客户的核心数据库存储问题导致数据库重启后无法正常启动,根据客户反馈最开始在启动数据库时
报错控制文件IO错误,如下:

上述的问题本质上都跟控制文件有关系,替换掉损坏的控制文件就行。当替换掉控制文件之后,在open数据库时发现报如下错误:

该错误本质上是因为redo的问题,即有redo log损坏。通过在RMAN进行recover,发现报如下类似错误:

上述过程大致是客户之前的处理过程。我在18点左右介入之后,进行了相关的操作。我最开始尝试在利用RMAN 进行恢复,发现报错:

从上面的错误来看,初步可以判断redo04a.log文件已经损坏,而且是block 1788672的问题。为了验证该block是否损坏,我通过类似如下的dump 命令进行dump,发现报错:

由此判断,该block损坏无疑。 由于客户的需求是尽可能快的将数据库拉起来,因此对应redo损坏的情况之下。
通常只能进程不完全恢复并强制打开,这里我使用了如下的参数:

在open resetlogs之前,我已经将redo备份,resetlogs打开时,发现数据库报错如下:

从日志来看,大致判断可能是_SYSSMU25$ 回滚段的问题,因此尝试先通过如下隐含参数屏蔽回滚段:

屏蔽回滚段之后,尝试打开数据库,发现错误依旧,通过10046 trace跟踪,发现递归SQL在如下的block上执行失败:

通过dump file 1 block 91,发现该block上第2个ITL确认存在一个活跃事务。原本计划直接bbed提交该事务,但是当我编译好bbed之后,查看发现该block为一个cluster block.

对于cluster block的事务修改,相对复杂一些,我的博客有文章描述,大家可以参考,这里不多说。考虑到生产库使用bbed有一定的风险,我并没有使用bbed。

接着使用undo_management参数启动数据库,然后强制open数据库,发现错误变成如下:

从错误来看,我们就可以知道,这应该是SCN的问题。如果要手工推进SCN,那么level应该待遇3297*4才行,由于这里的238091117/1024/1024/1024小于1,因此推进scn时,level=3297*4+2 就差不多了。 这里我再次进行了10046 trace,发现了如下信息:

bscn: 0xce1.e379b05 将该scn进行转换,我们可以发现:0xce1 为3297,e379b05为238525189. 与上述报错信息一致。同时我发现这里使用了第2号回滚段,如下:

因此,尝试继续使用隐含参数屏蔽这第2号回滚段,并尝试打开数据库,但是错误依旧。看来还是需要调整SCN才行,如下:

首先我尝试了在会话级别设置:

发现alter database open失败,尝试使用*._minimum_giga_scn参数,但是在启动的时候,提示说该参数不支持。从此判断,该环境可能是安装了比较新的PSU,Oracle将该参数废弃掉了,这么说前面的10015 event根本就没起作用。 无奈只能通过oradebug手工修改SCN来启动数据库了,如下:

修改SCN之后,顺利打开了数据库,但是数据库很快就crash掉,如下是日志信息:

从上述日志信息来看,主要出现了如下几个错误:

ORA-00600 [6006],ORA-00600 [4137],ORA-00600 [kdsgrp1]

对于前面2个错误,很明显是Oracle SMON进程在进行利用回滚段进行事务rollback时失败导致,如下:
ORACLE Instance xxxx2 (pid = 22) – Error 600 encountered while recovering transaction (44, 26) on object 47098.
ORACLE Instance xxxx2 (pid = 22) – Error 600 encountered while recovering transaction (48, 25).

因此,不难看出,数据库中还有部分的回滚段存在活跃事务。

对于ORA-00600 [kdsgrp1]错误,通常是出现在Index上,即Index数据和表的数据不一致,一般来说可以通过重建解决。

其次,对于后面的ORA-08102: index key not found, obj# 239, file 1, block 1674 (2) 错误,主要是job调用出现,因此
我们可以暂时屏蔽job的调度。

对于ORA-08102错误,我的博客几年前也写过相关的文章,本质上也是Index block中的相关键值不存在导致。

与其如此,最后我感觉将数据库的所有回滚段都屏蔽掉,并重建数据库undo 表空间,如下是获取回滚段的命令:

strings system01.dbf | grep _SYSSMU | cut -d $ -f 1 | sort -u

经过整理,发现该库存在大约2600个回滚段,我了个去,先不管这么多,重启实例后,重建undo表空间:

最后重启数据库实例,让客户将关键核心的配置表导出,先进行业务恢复,如果需要数据,直接从库中抽取。
这里要补充一点,该库约为5TB多一点,虽然有备份,但是恢复时间太长,如果有个dataguard是多么的重要啊!

某客户数据库崩溃同时dmp损坏的恢复案例

某客户的一个库系统损坏,导致oracle 崩溃,最后通过安全模式将数据文件拷贝出来,发现无法启动,非归档环境,

而且只有dmp 备份,之前他们通过dmp 备份进行了恢复,但是发现部分dmp 可能存在问题,导致部分表无法恢复,又尝试使用ODU进行数据文件的抽取,也发现部分表无法抽取(可能是system损坏较为严重,dbv检测有1000多个坏块)。

如下是尝试open时的alert log信息:

很明显,Oracle 在执行递归SQL的适合报错了,而且遇到了坏块。通过dbv检测,我发现存在大量的坏块,而且部分块还是连续损坏,极有可能是某个extent都损坏了。如下是dbv的检测结果: