某客户的一套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是多么的重要啊!

某大学的Oracle数据库恢复案例

某客户的数据库出现崩溃,无法正常启动,经过我的远程紧急救援恢复之后,恢复正常,如下是简单的处理过程,供参考!

在open数据库时,发现无法打开,报错如下:

对于上述错误,其实是比较常见的,大致上可以理解为Oracle在open 时需要进行一致性读的处理,却发现回滚段内容已经被覆盖,进而报错ora-01555,导致无法open。我们也可以发现,报错的SQL预计是Oracle 递归SQL,这是数据库在open时必须执行的SQL,很明显,该SQL无法执行成功,那么也就导致数据库无法正常打开。

处理思路很简单,首先我们要做的事情是通过10046 trace跟踪确认数据库在执行该SQL时访问了那些block,进而报错的?

通过oracle 10046 trace得到如下的内容:

根据我们常见的处理思路,将上述访问的block中的事务状态改成8000之后,发现仍然报错。我们仔细来对比下block中的scn与报错的scn信息,发现了其中的关系,如下:

将上述的scn bas值转换为10 进制后为:489416426,我们再来查询下数据库文件头的scn:

我们不难发现,报错的block中的scn比数据文件头的scn要大,其次也比前面报错的的scn:1d2be1e6 (转换后为 489415142)要大一些。这说明什么?

当数据库处于running的情况之下,Oracle 不知道下一个时间点事务什么时间结束,因此也不知道下一个时间点的scn是多少,所以其对应的scn 往往要比当前的大一些。当数据库crash后,加上undo损坏,那么很容易出现这样的情况。

所以,我们这要做的事情,很简单,将上述scn 修改得比报错的scn小一些(或者等于),则可以解决该错误。

修改之后,再次启动数据库,发现报错发生了变化,查看此时的alert log,发现信息如下:

很明显,这是scn的问题,要处理也很简单,通过推进scn即可解决掉。通过推进scn之后,发现打开数据库时,还是报错了,但是错误再一次发生了改变:

这次过程处理起来就很简单了,通过屏蔽undo就可以很容易解决掉。其次在后续的恢复过程中,还遇到了如下的一些错误:

这部分错误处理起来都相对简单的多。【4097】也是回滚段的问题,在处理undo时,可以一并处理之。我博客之前就写了该错误的处理案例,这里不再累述。这种恢复场景,最后打开数据库后一般还会有如下的错误:

最后这个错误处理起来十分简单,通过重建index即可解决上述错误,对于大量的 日志,建议直接grep,然后重建相关index即可。

最后通过mos的脚本来check 数据字典是否存在异常,这样就可以确保数据库起码可以正常运行。如下是检测结果:

我们可以发现,至少通过Oracle mos的脚本检查之后,没有数据字典有问题。

对于这样的复杂数据恢复,建议联系 云和恩墨 获取专业技术支持!