故障现象
由于机房UPS没有完善,开发库服务器在没有正常关闭数据库的情况下断电关闭,当服务器开机后,数据库启动失败,在open阶段提示:/opt/app/oradata/orcl/system01.dbf不一致,需要介质恢复。
故障处理背景
由于该开发库只有逻辑备份,没有物理备份,并且逻辑备份只是备份了数据库结构,并没有真实的数据,虽然开发库数据不是很重要,但由于开发人员都在上面进行项目开发,包含了最新的表结构和测试数据,所以希望尽可能打开数据库进行恢复。
处理过程分析
由于该库没有物理备份,所以直接覆盖还原(restore/recover方式)是不可能的,所以只能用recover尝试,由于断电前控制文件更新异常,于是用recover database using backup controlfile until cancel;方式尝试进行恢复,但失败,仍然提示系统表空间不一致,不能open;最后,用重建控制文件的方法(noresetlogs选项),对控制文件重建后,数据库可以正常启动,重建控制文件的脚本如下:
[oracle@oracledev ~]$ more createctl.sql
STARTUP NOMOUNT
CREATE CONTROLFILE REUSE DATABASE "ORCL" NORESETLOGS ARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 1168
LOGFILE
GROUP 2 (
'/home/oracle/oradata/orcl/REDO02.LOG',
'/home/oracle/oradata/orcl/REDO02_new.LOG'
) SIZE 200M BLOCKSIZE 512,
GROUP 3 (
'/home/oracle/oradata/orcl/REDO03.LOG',
'/home/oracle/oradata/orcl/REDO03_new.LOG'
) SIZE 200M BLOCKSIZE 512,
GROUP 4 (
'/home/oracle/oradata/orcl/redo4.log',
'/home/oracle/oradata/orcl/redo4_new.log'
) SIZE 400M BLOCKSIZE 512
DATAFILE
'/home/oracle/oradata/orcl/system01.dbf',
'/home/oracle/oradata/orcl/sysaux01.dbf',
'/home/oracle/oradata/orcl/undotbs01.dbf',
'/home/oracle/oradata/orcl/users01.dbf',
'/home/oracle/oradata/orcl/devtest01.dbf',
'/home/oracle/oradata/orcl/Mola_Pur_Data01.dbf',
'/home/oracle/oradata/orcl/MOLA_PUR_Index01.dbf',
'/home/oracle/oradata/orcl/MOLA_WMS7_Data01.dbf',
'/home/oracle/oradata/orcl/MOLA_WMS7_Index01.dbf',
'/home/oracle/oradata/orcl/Mola_PCenter01.ora',
'/home/oracle/oradata/orcl/OPC_INDEX01.dbf',
'/home/oracle/oradata/orcl/OMS_DATA01',
'/home/oracle/oradata/orcl/OMS_Index01.ora',
'/home/oracle/oradata/orcl/ OMS_DATA01.ora',
'/home/oracle/oradata/orcl/FBS_DATA01.dbf',
'/home/oracle/oradata/orcl/CRM_DATA01',
'/home/oracle/oradata/orcl/CRM_IDX01',
'/home/oracle/oradata/orcl/CRM_DATA02',
'/home/oracle/oradata/orcl/msg_data01',
'/home/oracle/oradata/orcl/msg_idx01.dbf',
'/home/oracle/oradata/orcl/invoice_data01',
'/home/oracle/oradata/orcl/invoice_idx01.dbf',
'/home/oracle/oradata/orcl/ysxt_data01',
'/home/oracle/oradata/orcl/ysxt_idx01.dbf',
'/home/oracle/oradata/orcl/yfxt_data01',
'/home/oracle/oradata/orcl/yfxt_idx01.dbf',
'/home/oracle/oradata/orcl/Mola_SC_data01',
'/home/oracle/oradata/orcl/Mola_SC_idx01.dbf',
'/home/oracle/oradata/orcl/Mola_DMS_data01',
'/home/oracle/oradata/orcl/Mola_DMS_idx01.dbf',
'/home/oracle/oradata/orcl/Mola_DMSTemp_data01',
'/home/oracle/oradata/orcl/Mola_DMSTemp_idx01.dbf',
'/home/oracle/oradata/orcl/move_test_data01',
'/home/oracle/oradata/orcl/move_test_idx01.dbf',
'/home/oracle/oradata/orcl/pmc_dev_data01',
'/home/oracle/oradata/orcl/pmc_idx01.dbf',
'/home/oracle/oradata/orcl/PCM_DATA01.dbf',
'/home/oracle/oradata/orcl/PCM_Index01.dbf',
'/home/oracle/oradata/orcl/SMM_DATA',
'/home/oracle/oradata/orcl/SMM_INDEX01.ORA',
'/home/oracle/oradata/orcl/WSS_DEV_DATA01.dbf',
'/home/oracle/oradata/orcl/WSS_DEV_INDEX01.dbf',
'/home/oracle/oradata/orcl/HQS_DEV_DATA01.dbf',
'/home/oracle/oradata/orcl/HQS_DEV_INDEX01.dbf',
'/home/oracle/oradata/orcl/MSG_DATA2.dbf',
'/home/oracle/oradata/orcl/PMC_INDEX01.dbf',
'/home/oracle/oradata/orcl/OPC_DEV1_01',
'/home/oracle/oradata/orcl/edm_data',
'/home/oracle/oradata/orcl/O2Odata01.dbf',
'/home/oracle/oradata/orcl/O2Oidx01.dbf'
CHARACTER SET AL32UTF8;
RECOVER DATABASE
ALTER SYSTEM ARCHIVE LOG ALL;
ALTER DATABASE OPEN;
注:这里用noresetlogs方式打开的意义是,以redolog的最后scn为准,把其scn更新到控制文件里去,这样是不会丢数据的;反之用resetlogs方式打开,则重建所有redolog文件,数据库会丢失重做日志里的内容。
打开后的异常现象
虽然开发库正常启动了,大部分的数据也是正常状态,可以查询访问,但数据库警告日志里却频繁报ORA-600错误,而且所有的动态性能视图访问异常。抛出的异常错误是:ORA-00600: internal error code, arguments: [kdsgrp1],经分析,该错误码[kdsgrp1]有好几种触发条件,其中一种是数据一致性异常导致,这个也在后面的诊断中得到了证实。查看ORA-600生成的跟踪文件,发现有数据访问了坏块,出现异常,具体描述为:
* kdsgrp1-1: *************************************************
row 0x0041ab59.54 continuation at
0x0041ab59.54 file# 1 block# 109401 slot 84 not found
KDSTABN_GET: 0 ..... ntab: 1
curSlot: 84 ..... nrows: 77
kdsgrp - dump CR block dba=0x0041ab59
Block header dump: 0x0041ab59
Object id on Block? Y
seg/obj: 0x1a8 csc: 0x04.79cdff02 itc: 6 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x417c40 ver: 0x01
这里红色报错信息部分为系统表空间的某个块出现不一致,导致数据访问失败,尝试经过文件号与块号去查该数据库对象,但失败了,原因是dba_extents表访问也出现异常,这给诊断过程带来不少障碍,后来经过资料查找,发现10231事件可以跳过所有坏块对对象进行访问,于是在参数文件加入以下设置,动态性能视图访问正常:
event="10231 trace name context forever, level 10"
至此,数据库大部分功能都可以正常运作了,包括EXPDP备份,于是赶紧通 过远程做了一个全备,这个全备也作为后面新开发库部署之用。
后续异常
虽然开发库启动后,跳过了坏块,数据库大部分功能都正常,数据也没丢失,但开发人员反映该库不能创建表等对象,并且此时警告日志还是偶尔报ORA-600错误,经过排查分析,该坏块是一个系统表里的坏块,查询定位:
Select owner, segment_name, segment_type, partition_name,tablespace_name
From dba_extents
Where relative_fno = 1
And 109401 between block_id and (block_id+blocks-1);
--OWNER --SEGMENT_NAME --SEGMENT_TYPE --TABLESPACE_NAME
SYS HIST_HEAD$ TABLE SYSTEM
该表为sys用户下的一个内部表,经分析,里面主要是存储了一些直方图的统计信息元数据,该表的某个块出现异常,虽然全表访问该表会跳过该坏块,正常返回数据,但数据会丢失一部分,但如果通过索引访问该块,索引的键值跟数据表内容不一致,便会出现这种ORA-600错误,这在前面的分析中提到。这种情况,如果有物理备份,直接通过RMAN的块修复功能即可解决,但由于没有物理备份,而且是系统内部表,所以暂时没有更好的办法解决,于是选择用逻辑备份出来的数据文件,在新部署的开发库中进行还原来解决这个问题。
总结
由于没有物理备份,这次故障事件的诊断过程还是比较曲折的,并且最后只能选择把数据迁移至新环境,所幸的是该次坏块所在的表并非核心的数据字段表,这样数据库还是可以正常打开,并且大部分功能还是可以用到(如EXPDP),这样可利用重新备份还原到新环境。
所以这次事件启发了两个问题:
1,物理备份对于介质恢复很重要;
2,数据库尽量正常关闭,避免这种断电重启行为。
很有实战意义!