Oracle数据恢复:Oracle RAC系统Redo/Undo损坏恢复

昨天,一个客户的数据库系统出现故障,RAC无法启动,大量的错误信息,经过分析检查,最后我们通过强制手段打开数据库,帮助用户挽回了数据损失。

故障的起因应该是主机和存储之间出现连接故障,message信息里可以看到大量如下提示:

Jun  1 19:57:18 Oracle-02 kernel: end_request: I/O error, dev sdb, sector 12931135
Jun  1 19:57:18 Oracle-02 kernel: sd 6:0:0:1: Device not ready: <6>: Current: sense key: Not Ready
Jun  1 19:57:18 Oracle-02 kernel:     Add. Sense: Logical unit not accessible, asymmetric access state transition
Jun  1 19:57:18 Oracle-02 kernel:
Jun  1 19:57:18 Oracle-02 kernel: end_request: I/O error, dev sdb, sector 12931647
Jun  1 19:57:18 Oracle-02 kernel: sd 6:0:0:1: Device not ready: <6>: Current: sense key: Not Ready
Jun  1 19:57:18 Oracle-02 kernel:     Add. Sense: Logical unit not accessible, asymmetric access state transition
Jun  1 19:57:18 Oracle-02 kernel:
Jun  1 19:57:18 Oracle-02 kernel: end_request: I/O error, dev sdb, sector 12932671
Jun  1 19:57:18 Oracle-02 kernel: sd 6:0:0:1: Device not ready: <6>: Current: sense key: Not Ready
Jun  1 19:57:18 Oracle-02 kernel:     Add. Sense: Logical unit not accessible, asymmetric access state transition

一旦出现IO写失败或者写丢失,则数据库将遭受数据损失,一旦UNDO和REDO损坏,数据库就将会无法启动。

在数据库的告警日志层面,首先出现的错误是如下类型:

WARNING: Read Failed. group:3 disk:0 AU:102 offset:16384 size:16384
WARNING: failed to read mirror side 1 of virtual extent 0 logical extent 0 of file 256 in group [3.3870646521] from disk REDO1  allocation unit 102 reason error; if possible,will try another mirror side
WARNING: Read Failed. group:3 disk:0 AU:102 offset:16384 size:16384
WARNING: failed to read mirror side 1 of virtual extent 0 logical extent 0 of file 256 in group [3.3870646521] from disk REDO1  allocation unit 102 reason error; if possible,will try another mirror side

这些错误首先提示REDO写操作失败,读写AU单位失败,这类错误信息教Oracle 11gR2之前详细了很多,精确到了AU单位及Offset。

在启动过程中出现了ORA-00600错误:

ARC0: STARTING ARCH PROCESSES COMPLETE
Redo thread 2 internally disabled at seq 1 (CKPT)
ARC2: Archiving disabled thread 2 sequence 1
Archived Log entry 785 added for thread 2 sequence 1 ID 0x0 dest 1:
Use ADRCI or Support Workbench to package the incident.
See Note 411.1 at My Oracle Support for error and packaging details.
Errors in file /oracle/diag/rdbms/spsp/SPSP1/trace/SPSP1_ora_19044.trc:
ORA-00600: internal error code, arguments: [2662], [0], [7291890], [0], [7314785], [12583040], [], [], [], [], [], []
Errors in file /oracle/diag/rdbms/spsp/SPSP1/trace/SPSP1_ora_19044.trc:
ORA-00600: internal error code, arguments: [2662], [0], [7291890], [0], [7314785], [12583040], [], [], [], [], [], []

Errors in file /oracle/diag/rdbms/spsp/SPSP2/trace/SPSP2_smon_14335.trc  (incident=291384):
ORA-00600: internal error code, arguments: [4194], [], [], [], [], [], [], [], [], [], [], []
Incident details in: /oracle/diag/rdbms/spsp/SPSP2/incident/incdir_291384/SPSP2_smon_14335_i291384.trc
Use ADRCI or Support Workbench to package the incident.
See Note 411.1 at My Oracle Support for error and packaging details.

注意Oracle 11gR2的提示,非常详尽,居然提示你通过My Oracle Support去参考 Note 411.1 学习ADRCI知识。

ORA-600的 4193 和 4194 错误,可以通过重建回滚表空间解决。
此处需要提醒的是,Oracle 11g的缺省UNDO段命名,增加了一个Unix Time的时间戳在回滚段名称里,如下所示:

SQL> select * from v$rollname;

USN NAME
———- ——————————
0 SYSTEM
31 _SYSSMU31_1012201531$
32 _SYSSMU32_3505455792$
33 _SYSSMU33_760762808$
34 _SYSSMU34_2022544229$
35 _SYSSMU35_774751923$
36 _SYSSMU36_3132287946$
37 _SYSSMU37_1634453262$
38 _SYSSMU38_1341527290$
39 _SYSSMU39_2970077311$
40 _SYSSMU40_1403026629$

在设置初始化参数时大致设置如下:

  _allow_resetlogs_corruption= TRUE
_offline_rollback_segments= “_SYSSMU11_1202330240$”
_offline_rollback_segments= “_SYSSMU12_1617713323$”
_offline_rollback_segments= “_SYSSMU13_1359816937$”
_offline_rollback_segments= “_SYSSMU14_2078039711$”
_offline_rollback_segments= “_SYSSMU15_1538259293$”
_offline_rollback_segments= “_SYSSMU16_3126366281$”
_offline_rollback_segments= “_SYSSMU17_2553547900$”
_offline_rollback_segments= “_SYSSMU18_1481844821$”
_offline_rollback_segments= “_SYSSMU19_135756661$”
_offline_rollback_segments= “_SYSSMU20_2322289537$”
_corrupted_rollback_segments= “_SYSSMU11_1202330240$”
_corrupted_rollback_segments= “_SYSSMU12_1617713323$”
_corrupted_rollback_segments= “_SYSSMU13_1359816937$”
_corrupted_rollback_segments= “_SYSSMU14_2078039711$”
_corrupted_rollback_segments= “_SYSSMU15_1538259293$”
_corrupted_rollback_segments= “_SYSSMU16_3126366281$”
_corrupted_rollback_segments= “_SYSSMU17_2553547900$”
_corrupted_rollback_segments= “_SYSSMU18_1481844821$”
_corrupted_rollback_segments= “_SYSSMU19_135756661$”
_corrupted_rollback_segments= “_SYSSMU20_2322289537$”

屏蔽了事务的回滚与重做之后,数据库被成功打开。

SQL> select * from v$version;

BANNER
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 – 64bit Production
PL/SQL Release 11.2.0.2.0 – Production
CORE    11.2.0.2.0      Production
TNS for Linux: Version 11.2.0.2.0 – Production
NLSRTL Version 11.2.0.2.0 – Production

数据库风险随时可能发生,备份必不可少啊

ORA-00600 kclchkblk_4 错误恢复案例一则

最近客户在恢复数据库时遇到了ORA-600 kclchkblk_4错误,这个错误在MOS上有官方的解释和解决方案。

在以下错误提示下:

Errors in file /u01/app/oracle/admin/orcl/bdump/orcl_smon_7493.trc:
ORA-600: internal error code, arguments: [kclchkblk_4], [1904],[18446744073431179384], [1904],18446744073403569507], [], [], []

Starting background process QMNC
QMNC started with pid=24, OS id=8329

Errors in file /u01/app/oracle/admin/orcl/bdump/orcl_smon_7493.trc:
ORA-600: internal error code, arguments: [2662], [1904], [3988985522],[1904], [4016595064], [8388610], [], []

Errors in file /u01/app/oracle/admin/orcl/bdump/orcl_smon_7493.trc:
ORA-600: internal error code, arguments: [2662], [1904], [3988985525],[1904], [4016595064], [8388610], [], []
SMON: terminating instance due to error 474
Instance terminated by SMON, pid = 7493

其问题,可能是由于临时表空间的SCN问题导致的,可以尝试删除所有的临时文件,启动数据库,通常可能正常启动。
可能的采取步骤是,在Mount状态下确定并删除临时文件:

    SQL>select file_name, file_id from dba_temp_files;
SQL>alter database tempfile_name drop;
SQL>alter tablespace add tempfile size N;

如果数据库能够成功启动,可以重建临时文件。

顺便引用一下ITPUB上一个朋友的帖子供参考: http://www.itpub.net/thread-1404451-1-1.html

问题描述:
服务器突然故障死机,导致数据库无法驱动,redo的CURRENT组的损坏。oracle 10g rac环境,asm磁盘组,redhat linux系统。每个组一个成员这个是组被破坏无法修复的关键。
没有归档,没有备份。使用ASM无法将数据文件冷备份出来。

ORA-00368: checksum error in redo log block
ORA-00353: log corruption near block 254606 change 12131176305969 time 03/08/2011 01:03:00
ORA-00312: online log 2 thread 1: ‘+DG1/police/onlinelog/group_2.258.657430669’

查看日志组文件信息,报错的日志组为CURRENT模式。

SQL> select group#,sequence#,archived,status from v$log;

GROUP#  SEQUENCE# ARC STATUS
———- ———- — —————-
1      17495 NO  INACTIVE
2      17496 NO  CURRENT
3      17365 NO  INACTIVE
4      17366 NO  CURRENT

组成员只有一个。

SQL>

Group   Instance             Member             STATUS             Size(MB)
———- ———- —————————— —————- ———-
1          1 +DG1/police/onlinelog/group_1. INACTIVE                500
257.657430665

2          1 +DG1/police/onlinelog/group_2. CURRENT                 500
258.657430669

3          2 +DG1/police/onlinelog/group_3. INACTIVE                500
265.657431819

4          2 +DG1/police/onlinelog/group_4. CURRENT                 500
266.657431825

无法使用clear命令清楚redo的信息

SQL> alter database clear unarchived logfile group 2
2  ;
alter database clear unarchived logfile group 2
*
ERROR at line 1:
ORA-01624: log 2 needed for crash recovery of instance police1 (thread 1)
ORA-00312: online log 2 thread 1: ‘+DG1/police/onlinelog/group_2.258.657430669’

SQL> alter database clear logfile group 2;
alter database clear logfile group 2
*
ERROR at line 1:
ORA-01624: log 2 needed for crash recovery of instance police1 (thread 1)
ORA-00312: online log 2 thread 1: ‘+DG1/police/onlinelog/group_2.258.657430669’

处理步骤

把数据库down掉

   SQL>shutdown immediate

5、在init<sid>.ora中加入如下参数

_allow_resetlogs_corruption=TRUE

6、重新启动数据库,利用until cancel恢复

SQL>recover database until cancel;
Cancel

如果出错,不再理会,发出

SQL>alter database open resetlogs;

如果运气好的话可以正常启动数据库,就可以导出数据了。但是这里有点意外不知道是点背还是rac环境的恢复比较特殊。在alert.log中有如下报错:

Errors in file /u01/app/oracle/admin/police/bdump/police2_j003_17720.trc:
ORA-00600: internal error code, arguments: [4194], [9], [8], [], [], [], [], []
Wed Mar  9 18:08:06 2011
Errors in file /u01/app/oracle/admin/police/bdump/police2_j004_17722.trc:
ORA-00600: internal error code, arguments: [4193], [55749], [55753], [], [], [], [], []
Wed Mar  9 18:08:08 2011
Errors in file /u01/app/oracle/admin/police/bdump/police2_mmon_11328.trc:
ORA-00600: internal error code, arguments: [4194], [12], [17], [], [], [], [], []
Wed Mar  9 18:08:08 2011
Errors in file /u01/app/oracle/admin/police/bdump/police2_j002_17718.trc:
ORA-00600: internal error code, arguments: [kcbz_check_objd_typ_3], [0], [0], [1], [], [], [], []

能后我就重复启动数据库这个错误就过去了,网上有一篇文档是这么说的,真的可以过去,不过我是将两个节点都同时启动的时候过去的,但是在开始出现如下错误:
ORA-600[KCLCHKBLK_4]【2824】,但是没有出现ORA-600[2662]的报错,不知道为什么,有人说是temp文件不一致造成,但是别人都有2662的报错我这里没有,不管了先将temp删了在说。

能后速度将temp删除,能后发现问题依旧。当时我就很失望了,情绪低落。这个报错在网上的解决办法只有这一个。也没有什么人有更好的建议。
ORA-00600: internal error code, arguments: [kclchkblk_4], [2824], [18446744071603238605], [2824], [18446744071593491338], [], [], []
Wed Mar  9 14:29:55 2011
Errors in file /u01/app/oracle/admin/police/udump/police1_ora_27660.trc:
ORA-00600: internal error code, arguments: [kclchkblk_4], [2824], [18446744071603238605], [2824], [18446744071593491338], [], [], []
Wed Mar  9 14:29:55 2011
Error 600 happened during db open, shutting down database
USER: terminating instance due to error 600

但是仔细观察后我发现18446744071593491338这个数据有问题,它在我每次重新启动数据库的时候会和前面的数值有所改变18446744071593491338,我的目标就是将
这个数值尽量的缩小和18446744071603238605的值,重复几遍后发现使用srvctl start database -d sid数据库会自动重启多次,我就不停地启动关闭。有希望了两个者还是相差太大,
这一步我们在这里卡了很久。这里有一个scn的问题,我这里碰到的是后面的比前面的低,所以adjust_scn没有效果。
无赖我将_allow_resetlogs_corruption=TRUE增加到spfile中让数据库同时启动。结果发现错误改变了,后来想想估计是要将参数添加到spfile中同时启动数据库才有效果,因为我单独启动数据库的时候效果不大。

Errors in file /u01/app/oracle/admin/police/bdump/police2_smon_11322.trc:
ORA-00600: internal error code, arguments: [4137], [], [], [], [], [], [], []
Wed Mar  9 18:08:35 2011
ORACLE Instance police2 (pid = 16) – Error 600 encountered while recovering transaction (9, 46).
Wed Mar  9 18:08:35 2011
Errors in file /u01/app/oracle/admin/police/bdump/police2_smon_11322.trc:
ORA-00600: internal error code, arguments: [4137], [], [], [], [], [], [], []
Wed Mar  9 18:08:35 2011
Trace dumping is performing id=[cdmp_20110309180835]
Wed Mar  9 18:08:37 2011
Errors in file /u01/app/oracle/admin/police/bdump/police2_smon_11322.trc:
ORA-00600: internal error code, arguments: [4137], [], [], [], [], [], [], []
Errors in file /u01/app/oracle/admin/police/bdump/police2_p007_19333.trc:
ORA-00600: internal error code, arguments: [4198], [9], [], [], [], [], [], []

出现了这些报错,现在好了,4137,4138 ,4139不都是undo的报错吧,
新建立两个undo,修改spfile使用新的undo启动,删除旧的undo。
添加spfile参数

_allow_resetlogs_corruption”=true ”
_allow_terminal_recovery_corruption”=true
_corrupted_rollback_segments =’_SYSSMU1$’,’_SYSSMU2$’,’_SYSSMU3$’

如果不能确定多少个,但是我在删除UNDO的时候提示_SYSSMU2无法删除,我还是坚持加到了20个,后来我查了一下一共有400多个还好没有每个都坏掉。
修改undo_management 这个参数
把参数文件中的undo_management 改为MANUAL

SQL> create undo tablespace undotbs3 datafile ‘/opt/oracle/oradata/conner/undotbs3.dbf’ size 10M;
Tablespace created.
SQL> alter system set undo_tablespace=undotbs1 scope=spfile sid=’sid’;
System altered.
SQL> drop tablespace undotbs2;
Tablespace dropped.

将两个节点的undo都替换后发现数据库可以起来了,但还是有报错,

Errors in file /u01/app/oracle/admin/police/bdump/police2_j000_7977.trc:
ORA-00600: internal error code, arguments: [kcbz_check_objd_typ_3], [0], [0], [1], [], [], [], []
Wed Mar  9 23:56:10 2011

但还好可以exp数据了。

导出数据后,删除数据库,删除asm,
关闭第二台的asm实例,
登入第一台asm

SQL> select name from v$asm_diskgroup;
NAME
——————————
DG1
SQL> drop diskgroup DG1 including contents;       –>删除磁盘组
SQL>SHUTDOWN IMMEDIATE

最后
crs_unregister ora.node1.ASM1.asm
crs_unregister ora.node1.ASM1.asm(后来极度后悔,应该在unregister前备份一下就好了)
在dbs和admin下删除asm相关文档
修改/etc/oratab文件将asm的注释。
dbca重新建立asm磁盘发现asm实例无法启动晕倒。好像是出现prks-1011,和ora-0210的报错
使用srvctl add asm -n node1 -i +ASM1 -o $ORACLE_HOME -p init+ASM1.ora
提示ora.node1.ASM1.asm服务已经存在了,但是crs_stat -t查看又没有ora.node1.ASM1.asm服务。
于是我使用crs_register ora.node1.ASM1.asm的时候提示找不到 ora.node1.ASM1.asm.cap的文件(这里折腾了一段时间)
没法我从别的rac上使用crs_stat -p ora.node1.ASM1.asm > ora.node1.ASM1.asm.cap导出了一份拷贝到提示的目录下,并且修改了文件中的主机信息等。
在使用crs_register ora.node1.ASM1.asm就注册成功了。其实 ora.node1.ASM1.asm.cap这个文件的东西和 ora.node1.lsnr的文件内容一样。就是有些东西自己动手修改一下就可以替代了。
重新建库导入文件
艰苦的数据恢复终于完成了。

某大学的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的脚本检查之后,没有数据字典有问题。

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

3TB 非归档Oracle数据库恢复小case(windows)

这是一位网友的数据库恢复case,昨天圣诞节的时候来个求助,只能速度帮忙解决了好过节去了。首先我们来看下的alert log都有哪些信息:

我们可以看到,这个数据库已经宕机好几天了,在23号的时候就已经无法正常open了。上述的结果错误也很常见很简单。朋友经过处理后顺利把数据库open了,可是打开之后创建新的undo 表空间之后尝试重启后就再也打开不开了。遇到了如下的错误:

这个错误我也是第一次遇见。从kcbzpbuf函数来看,是dbwr进出写脏块时发现了坏块。很明显,从上面的坏块信息来看,dba地址0x0b07e8b2 和 rdba地址0x1c4ee895是不匹配,这肯定没法正常写入的。
针对这个错误我事后在metalink 搜索了一下,还是有不少相关的文档甚至是bug,这里不多说了。处理方式很简单,首先加入如下2个隐含参数尝试打开数据库:

*._allow_resetlogs_corruption=TRUE

*._allow_error_simulation=TRUE
做了不完全恢复后,尝试open resetlogs时发现遇到了如下错误:

看到这里2个错误,很多人可能会很迷惑,到底数据库无法open是因为哪个错误导致的呢? 这里稍微注意一下前后报错的顺序就知道了,很明显是前面的ora-00600 [2662]错误导致无法open resetlogs完成。
对于ora-00600 [2662]错误这里不再解释了,SCN的问题。这里直接推进scn即可。
将数据库启动到mount状态,执行如下命令:

很顺利就打开了数据库。由于之前朋友已经创建了新的undo表空间,我只需要帮忙把undo重建就完事了,结束支持任务。尝试进行drop tablespace undotbs1 including contents and datafiles时,遇到ora-01548错误。
在alter session set “_smu_debug_mode” = 4; 后都无法进行drop,那只能继续使用下隐含参数了:

通过这2个隐含参数,可以顺利将旧的undo 表空间drop掉,然后修改pfile文件去掉不需要的一些隐含参数,顺利打开数据库。
到这里结束我的半小时支持友情支持任务!悲剧的下午又开始优化某客户的SQL。。。。。

备注:

1) 对于这种异常强制打开的数据库,建议进行全库检查,包括是否有坏块等,甚至检查数据字典是否一致等等(实际上检查之前的alert log发现,    之前数据库在恢复过程中就报了不少的坏块)

2) 在这个年代,还有3TB的数据库,而且是windows,更悲剧的还是非归档,没有备份,这是不应该的。

3) 我们应该多考虑下系统的容灾建设,哪怕是有备份。

清明节某客户的11gR2 rac恢复案例

这是昨天节假如接到的某客户的紧急救援数据恢复案例。大致的情况是由于掉电导致数据库无法open。经过初步排查,确认数据库版本为Oracle 11.2.0.3(linux RAC),数据量比较小,

大约200G左右。整个恢复过程开始看上去很顺利,仅30分钟就顺利打开了数据库,后续发现其中确实有少坑,这里跟大家简单分享一下这个清明节加班的恢复case。

首先我们来看下数据库无法open所报的错误是什么?

这个错误其实很常见,已经遇到很多次了,处理方式也不难;大致上有两种.
1、通过10046 trace定位到有问题的数据块,然后手工去屏蔽事务;

2、推进数据库SCN
这里我选择使用推进scn的方式来进行处理。

直接通过oradebug poke修改scn;第一次修改可能是增加的scn不够大;第一次报错一样;第二次报错改变了;变成我们更加熟悉的错误:

 

上述的这个错误处理方式其实也有2种,大致如下:
1、由于scn差距很小,因此直接适当推进scn即可。

2、bbed修改dba地址20971648 中的事务来绕过该错误。

很明显,这里我选择第1种方法更简单;这里我再次修改scn,稍微增加大一点即可;很顺利的打开了数据库。

看上去整个恢复过程很简单,也就不到半小时就打开了数据库。可是当我检查数据库文件状态时,整个数据库一共有23个数据文件,其中有11个数据文件状态为missing,

这也就是说都无法识别到数据库文件。实际上此时数据库alert log中也在报如下的错误,告诉我们这部分数据文件无法识别:

由于此时数据库已经打开了,因此为产生了一个重建控制文件的脚本,发现脚本内容如下:

实际上我问客户,他们的反馈是之前由于控制文件损坏,客户也重建了控制文件,进行了多次恢复,而且也进行了resetlogs操作。

从上面的信息来看,不难看出客户重建控制文件的时候漏掉了11个数据文件。由于这部分文件的信息在数据字典中存在,因此在open的时候Oracle 会自动进行offline drop。
或许有人要说,直接找到文件然后重建控制文件不就行了吗?确实如此,然而实际上这里却并没有这么简单。
我进入到asm磁盘组检查文件发现有几个文件名称很奇怪,例如user_02.dbf 实际上link到了system,类似这样的情况。
这种情况下极容易出错。争取的做法查询dba_data_files进行数据文件的挨个确认。
确认好asm磁盘组漏掉的4个文件之后,还有7个文件位于文件系统中。全部添加到脚本中进行创建时发现这些文件和之前到文件到resetlogs已经完全不同了。
其实创建控制文件会报错ora-01189。
因此这里还必须手工去修改这11个数据文件头的resetlogs信息;等我将resetlogs信息全部修改完毕后,可以顺利创建控制文件。
但是当我进行reconver时却发现需要之前等archivelog,进一步检查发现归档日志都全部被删掉了。
因此最后还必须的再次修改这部分数据文件的checkpoint信息,将其改成与其他正常的文件一致,最后可以顺利打开数据库,

且检查所有的数据库文件状态均为online状态,如下所示:

最后再将文件系统的文件迁移到asm磁盘组,然后添加redo信息,启动rac节点2.

某客户Oracle RAC(4 TB ASM) 数据库恢复案例

6月底我们接到某客户的紧急支持请求,其客户数据库在不久前由于机房停电,导致数据库重启后无法启动。

我们通过teamviewer远程初步分析了alert log以及kfed读取了几个disk 发现,数据库无法启动的根本原因在于ASM diskgroup无法mount。而ASM diskgroup 无法mount的根本原因在于,ASM元数据出现损坏,其中表现为ASM 启动时无法进行事务恢复。

这里我们先不去纠结为什么会坏。对于asm的元数据如果出现损坏,那么修复的难度可想而知。

这里我采取了非常简单的数据库恢复方案,计划用AMDU抽取数据库文件,然后将数据库open,最后再重建原数据库磁盘组,最后通过Oracle rman 的backup as copy 方式将数据库还原回去。

想象是比较美好的,经过与客户长达1天的沟通协调之后,发现客户根本协调不到存储资源,而数据库环境本地可以空间也就不足100G。我们知道,整个数据库的磁盘组是6TB,其中数据库文件大约在4T左右,显然这是比较麻烦的事情。

无奈之下,客户从京东买了一个6TB的移动硬盘,经过一番努力之后,挂上移动硬盘,通过AMDU抽取文件测试,发现速度大约为5m/s。这是一个500m的undo文件复制到移动硬盘的速度测试:

大家可以计算一下,大约需要10天左右。这样是这样进行下去,那么整个恢复过程估计需要15天了,这是无法接受的。

后面跟客户了解了一下,客户的应用服务器是windows环境,我通过在windows共享文件,NFS共享到soalris,测试amdu抽取文件的速度大约可以达到15m/s。虽然这也是非常之慢的,但是相比之前已经好很多了,客户也可以接受了。

这里不得不说一下windows和Soalris之间配置NFS共享,也是一个比较麻烦的事情。折腾了几个小时才搞定这个问题。这里我简单记录一下配置的步骤,如下:

后续的步骤相对就简单了,都是传统的数据库恢复套路。如下是AMDU抽取文件的步骤:

这里我们需要注意的是,amdu不仅可以抽取数据文件,还可以抽取spfile、controlfile、以及redo、archivelog等。

对于AMDU工具抽取文件的过程,就单纯的命令而言,这是比较简单的。其中的关键就是我们必须知道文件在ASM diskgroup中对应的asm file number号。注意,这里的file number,并非数据库(DB)中的file number。

Oracle ASM的元数据中,其中alias directory 里面记录了数据库文件和asm 之间的一个映射关系。也就是说我们只要能够通过kfed读取alias 的数据,也就能够知道数据文件的asm file number是多少。

当然,很多情况之下,如果你添加数据库文件是alter tablespace xxx add datafile ‘+DATA’  …这样的方式,那么直接查询控制文件即可获得asm file number。这里不多说。

最后我dbv check了一下数据库文件,发现就undo存在几个坏块,其他文件均ok。不过比较郁闷的是,进行正常recover database恢复时,提示需要recover的归档找不到。这是怎么一回事呢?

我们来看下数据库文件头的scn 情况。

我们可以发现,从文件头的scn来看,差距大概在3个小时左右。而recover 时也确实需要比较旧的archivelog。而这中间差距的几个小时的归档,我们通过kfed 读取asm diskgroup元数据发现并没有找到。

为什么会丢失呢?其实很简单,可能这3个小时的归档也就6个archivelog,很可能在存储cache中,并没有写入到磁盘上。那么当掉电之后,这几个archivelog 肯定也丢失了。

当归档不全的情况之下,我们amdu抽取的current redo logfile已经没有意义了。我们只能将该数据库强制open,然后重建数据库。这里我简单描述一下数据库的open过程,以及恢复过程中遇到的一些错误:

首先利用amdu 抽取的控制文件进行mount,发现报如下错误:

这个错误很常见,我们在数据库恢复过程中经常碰到该错误。假设你是第一次遇到这个错误,你该如何判断该错误是什么问题?跟什么东西有关系呢?从ORA-00600错误的关键字,kccpb可以看出,这跟控制文件有关系,其中还包含了check关键字。说明这是在数据库mount过程中,进行某些check检查,发现了某些数据异常。那么后面的2个数字:3811063,3770626是什么意思呢?

有人或许会说,这有没有可能是scn?这里不排除这种可能性,如果你稍微有一定经验,那么很容易排除这个可能性。为什么?

首先对于一个运行超过3年的Oracle数据库,scn不可能这么小。其次从Oracle 10g开始,会自动产生snap controlfile的备份,在ORACLE_HOME/dbs目录下,我们可以利用该备份进行mount,然后去检查数据库文件的scn情况。

那么这个错误到底是什么意思呢?这里我猜测肯定是某个sequence number的东西,Oracle在mount的过程中认为读取的数据应该是3811063,但是实际上读取的数据确实3770626,2者之间存在差异。也就是说,Oracle认为控制文件已经损坏。

实际上,Oracle metalink 针对该错误进行了详细描述,其实也提供了解决方案,供大家参考:ORA-00600: [kccpb_sanity_check_2] During Instance Startup (文档 ID 435436.1)

看过该文档的人应该都知道,解决该错误的方法就是利用备份进行恢复,要么就是重建控制文件。既然如此,那么我们就来重建控制文件吧:

重建完毕之后,进行一次不完全恢复,然后尝试直接open数据库,发现遇到如下错误:

这个错误也很常见。很多人都已经知道如何处理这种情况下,那就是推进SCN。那么这里如何推进scn呢?

由于该数据库是Oracle 10g,且没有安装最新的psu;因此我们可以直接使用oracle 10015 event来推进scn,命令如下:

alter session set events ‘10015 trace name adjust_scn level n’;

其中的n表示level,那么这个level应该是多少呢?应该是4*7=28,为了稳妥期间,我们一般设置比28稍微大一点,因此可以设置30.

经过10015 event的处理之后,再次open数据库,你会发现数据库已经open了,但是很快就会crash。因为会如下错误:

同一,该错误也太常见了。我们知道,对于ORA-00600 后面的错误编号,如果是在4000–6000的范围中,那么表示跟undo有关系。实际上我们之前dbv检查文件也确实发现undo有极少量的坏块存在。那么这里怎么处理这个问题呢?

既然undo存在文件,那么我们知道数据库在open的时候需要进行事务的rollback,而事务回滚则跟undo存在极大关系。那么这里我们可以通过几种方式来解决该问题:

1、通过undo_manangment=manual

2、._offline_rollback_segments

3、10513 event来禁止smon 进行事务恢复.

很明显,这里我选择第一种方式,更为简单,通过修改pfile即可很快解决该问题。通过参数修改很顺利打开了数据库,然后检查alert log发现会有如下类似的错误:

该错误,我相信不少同学都遇到过。从该错误的提示来看,就非常明确了,index key not found。也就是说这是index的问题。那么是什么对象呢? 也就是我们的obj# 5099。 对于object号大于56的,那么我们可以直接rebuild处理。

alert log中其实还有一些其他的错误,这里我们不在一一列举说明。前面已经提到过,由于cache丢失,那么数据库中的很多数据可能都不一致,如果通过修复alert log中的错误,然后提供业务运行,那么存在极大的风险。因此建议重建数据库比较好一些。

这里我们首先将undo进行重建处理,这样可以绕过很多错误,接着开始进行数据库重建工作。

补充:提供几篇文档供大家参考:

Step by step to resolve ORA-600 4194 4193 4197 on database crash (文档 ID 1428786.1)

 

Oracle open遭遇ora-01555错误

前几天我们的一位准客户的其中一套较为重要的数据库出现了故障。我们这里先姑且不去分析原因,来将数据库打开提供业务恢复再说。首先我们来看下一线工程师现场发回的报道:

从上述的错误来看。数据库在open时,其中一个递归SQL语句执行失败,该递归SQL执行失败的原因是出现了ora-01555错误,即大家所熟知的快照过旧;同时日志中也明确提到了需要访问的回滚段编号,即第37号回滚段。

根据我们一般的处理思路,需要进行10046 trace跟踪,确认这里的递归SQL是不是访问了一些存在活动事务的Block

 

10046 跟踪来看,报错的SQL 语句访问了2block;分别是file 1 block 337file 157 block 164013. 很明显第一个数据块应该是数据字典的block,而157号文件的这个block应该是undo block,因为这里的obj#=0.

接着我们来看看file 1 block 337 blockdump情况:

 

block dump来看,这是一个Index Block。从ITL的信息来看,这个Index Block没有任何活动事务。同时,根据前面的10046 trace来看,报错的递归SQL访问的obj#=20,换成为16进制为c1 15,然而这个Index block 中并没有这个键值;同时我们dump了下一个index block 找到了对应的键值。

我们可以看出,这个index是一个复合索引,其中col 0的c1 15就是表示20. 该行数据对应的数据块地址是004000f100,转换为10进制是:4194545。

我们回到前面的这个问题,为什么递归SQL访问file block 337 然后接着需要去访问undo block呢? 而且从10046 trace来看fetch r=0,表明并没有获取到数据。说明问题仍然出在这个block的访问上。

这里我们进一步该block的dump来看,发现其scn如下:

当通过dump控制文件的scn来看,明显要小的多,如下:

我们将上述的database checkpoint进行转换:

很明显数据库的checkpoint 明显要比这个Index Block的scn小的多,也就势必导致数据库在启动的时候需要去访问Undo Block。所以这里经过单次的修改undo$  将对应的37号回滚段标记为offline都无法解决这个问题。这里我们首先尝试清除了file 1 block 377的ITL信息之后,启动数据库发现错误发生了改变,如下:

这个错误就非常明白了,就是block scn的问题。而报错的数据块地址为:4194545,这就是我们前面提到的4000f1这个数块,即file 1 block 241 这个数据块。

看起来这个错误本质上来说,可以直接推进scn解决问题。这里我们通过设置*._minimum_giga_scn参数来解决问题。通过设置了该参数之后,成功打开了数据库。

虽然数据库alert log后续还有一些ora-00600 [4097],ora-08102等错误,但是处理都相对简单了。通过重建undo、重建Index即可解决。