Oracle断电引起坏块的恢复案例

故障现象

         由于网络部服务器切换演练,开发库服务器在没有正常关闭数据库的情况下断电关闭,当服务器开机后,数据库启动失败,在open阶段提示:/opt/app/oradata/orcl/system01.dbf不一致,需要介质恢复。

 

故障处理背景

          由于该开发库只有逻辑备份,没有物理备份,并且逻辑备份只是备份了数据库结构,并没有真实的数据,虽然开发库数据不是很重要,但有些库对数据依赖性比较大,如OGG校验用户,CRM用户等,所以希望尽可能打开数据库进行恢复。

处理过程分析

          由于该库没有物理备份,所以直接覆盖还原(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,数据库尽量正常关闭,避免这种断电重启行为。