暂无图片
暂无图片
10
暂无图片
暂无图片
暂无图片

机房掉电LostWrite强制启库

原创 云和恩墨-曾令军 2020-01-20
3684

由于客户环境的日志数据无法取下来,也不便分享,因此本文的重点是描述问题处理方法和过程,数据均为虚构。

问题描述:

机房掉电所有设备都异常关闭,重新接电了发现很多测试库无法正常启动,没开归档没有备份,在这种情况下,考虑强制把数据库拉起来是最快的恢复方式。

无法正常启动的数据库很多,问题的场景可以分类归纳为以下几种:

  1. 控制文件写丢失,mount报ORA-3113错误
  2. redo文件写丢失,open报数据文件需要恢复
  3. 数据文件写丢失,SCN不一致无法open
  4. 数据表逻辑错误,部分业务运行时报600错误
  5. 基表逻辑错误,无法再新建表和索引

有些库只有其中一种现象,有些库是好几种现象的组合,理解和掌握每种问题的处理方法,就可以从容应对。
下面针对每一种问题现象分开描述其处理过程。

场景一:控制文件写丢失,mount报ORA-3113错误

ORA-03113: end-of-file on communication channel
检查trace文件,有以下描述内容:

Error: kccpb_sanity_check_2 Control file sequence number mismatch! fhcsq: 3014656 bhcsq: 3014678 cfn 0 rpbn 15

解决办法: 重建控制文件即可(由于控制文件损坏,需要手工编辑创建控制文件)

场景二:redo文件写丢失,open的时候报错, 数据文件正在恢复

ORA-01108:file 1 is in backup or media recovery ORA-01110:data file 1:'+xxxx/DATAFILE/SYSTEM.dbf'

检查确认:

  1. 在alert日志中,能查到如下信息:
ORA-00742: Log read detects lost write in thread %d sequence %d block %d
  1. 检查v$datafile_header,所有数据文件的SCN都是一致的
SQL> select distinct CHECKPOINT_CHANGE# from v$datafile_header; --结果只有一行

解决办法:

  1. 准备重建控制文件的内容
SQL> alter database backup controlfile to trace; --保留RESETLOGS case创建控制文件部分的内容
  1. 创建pfile, 修改参数文件,添加允许resetlog错误的参数
_allow_resetlogs_corruption=TRUE event="21307096 trace name context forever,level 3" --如果是12C版本,还要把这个event加上才生效
  1. 尝试启动数据库
startup nomount pfile='/home/oracle/pfile'; CREATE CONTROLFILE REUSE DATABASE "TEST12C" RESETLOGS NOARCHIVELOG ...重建控制文件,后面的内容略... RECOVER DATABASE USING BACKUP CONTROLFILE --输入CANCEL alter database open resetlogs; ALTER TABLESPACE TEMP ADD TEMPFILE '+DATA/TEST12C/TEMPFILE/temp.264.134134134' REUSE; --添加新的临时文件
  1. 通常起来之后,又会马上DOWN掉,而且报ORA-600[2662] ORA-600[4193]之类的错误,需要对Undo表空间做处理:
1)修改参数文件: *.undo_tablespace='SYSTEM' undo_management=MANUAL 2)启动数据库,如果还是报错并自动重启,需要把有问题的undo段排除掉 select to_char(wm_concat(SEGMENT_NAME)) from dba_rollback_segs WHERE tablespace_name='UNDOTBS1'; 一次性把原undo表空间的所有rollback段全部放到pfile参数列表中: _OFFLINE_ROLLBACK_SEGMENTS=(_SYSSMU248_13423244$,_SYSSMU248_341343244$) 3)重启数据库后,要删除旧的undo表空间,不然会一直自动重启 创建新的undo表空间 create undo tablespace undotbs2 datafile '+DATA/TEST12C/DATAFILE/undotbs2.dbf' size 100m autoextend on next 100m maxsize 30g; 删除旧的undo表空间 drop tablespace undotbs1 including contents and datafiles; 4. 把临时添加的参数删掉,重新创建SPFILE后,正常启动

场景三:数据文件写丢失,SCN不一致无法open

open resetlogs时,报错:

ORA-00600 [kcbgtcr_13],[],[],[],[]

这个场景的问题现象和处理方法与场景二类似,只是在检查确认的时候,会发现数据文件头有多个SCN:

select distinct CHECKPOINT_CHANGE# from v$datafile_header; --结果有多行,表示有多个数据文件SCN不一致

处理过程基本与场景二相同,差别在于重建控制文件之后,多一个手工推进SCN的操作,推进方法如下:

SQL>col CHECKPOINT_CHANGE# for 9999999999999999999 SQL>select distinct CHECKPOINT_CHANGE# from v$datafile_header; 135016264047 --记录当前SCN,控制文件重建后SCN变成一样了,但仍需推进 SQL>oradebug setmypid SQL>oradebug dumpvar sga kcsgscn_ kcslf kcsgscn_ [700000000019B70, 700000000019BA0) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 07000000 00019850 SQL> oradebug poke 0x700000000019B70 8 135026264047 (最后一个参数需要修改到比当前文件scn大,这里推进了10000000) BEFORE: [700000000019B70, 700000000019B78) = 00000000 00000000 AFTER: [700000000019B70, 700000000019B78) = 0000001F 6F9A380F SQL>oradebug dumpvar sga kcsgscn_ kcslf kcsgscn_ [700000000019B70, 700000000019BA0) = 0000001F 6F9A380F 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 07000000 00019850

推进后,后面的处理步骤相同, 修改resetlog参数、处理undo段、resetlog打开数据库

场景四:数据表逻辑错误,部分业务运行时报600错误

数据库拉起来了,但是业务运行过程中,有部分业务运行时抛出错误,检查后台日志:

ORA-00600:[kdifind:kcbz_ojbdchk],[0],[0],[1] 或者 ORA-00600:[6002],[6],[0],[2]

这是因为掉电时,数据写入出现不一致,有些数据在索引上的字段键值与数据块上的字段值对不上。

处理方法:
复制索引创建语句,把原索引删除,再重新创建索引,错误就排除了。如果表上有很多索引,不确定是哪一个报出来的,就用如下方法,检查验证:

set autotrace traceonly --只执行不显示结果 select /*+index(a,index_name)*/* from test_tab a;

走索引然后回表,验证索引与表的数据是否一致

场景五:基表逻辑错误,无法再新建表和索引

数据库拉起来了,但是建表的时候报错:

ORA-00604: error occurred at recursive SQL level 1 ORA-08102: index key not found, obj# 39, file 1, block 234 (2)

这是因为掉电时,OBJ数据写入出现不一致,有些数据在索引I_OBJ4的字段键值与OBJ数据块上的字段值对不上。

处理方法:
由于bootstrap$中的对象都不允许直接删除或重建,需要用到BBED修改数据块的对象号。

1. 通过走索引和走全表的方式,找出错误数据 select /*+ index(t i_obj4) */ DATAOBJ#,rowid from obj$ t minus select /*+ full(t1) */ DATAOBJ#,rowid from obj$ t1; ---------- ------------------- 23456 AAAAASAABAAABHcAAW select /*+ full(t1) */ DATAOBJ#,rowid from obj$ t1 minus select /*+ index(t i_obj4) */ DATAOBJ#,rowid from obj$ t; ---------- ------------------- 23464 AAAAASAABAAABHcAAW --会发现同一个rowid对应的dataobj#却不相同 2. 找到块号和行号 select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#, dbms_rowid.rowid_row_number(rowid) row# from obj$ where rowid='AAAAASAABAAABHcAAW' ------ ------ ------ 1 4572 22 --这里是第4572号块,第22行 3.记录要修改的值 select dump(23456,16) from dual; ---------------------------- Typ=2 Len=4: c3,3,23,39 select dump(23464,16) from dual; Typ=2 Len=4: c3,3,23,41 4. 使用BBED编辑数据 把库停掉,拷贝一个system.dbf出来修改 bbed filename=/home/oracle/TESTDB/DATAFILE/system.dbf blocksize=8192 BBED> set block 4572 --第4572号块 BBED> p *kdbr[22] --第22行 BBED> x /rnnncnnncc --显示当前行数据 rowdata[5244] @6389 ------------- flag@6389: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@6390: 0x00 cols@6391: 18 col 0[3] @6392: 1033 col 1[3] @6396: 23456 --这里就是ob$表中的对象号,需要把这个值修改成23464 col 2[1] @6400: . col 3[25] @6402: TAB_OBJECT col 1[4] @6428: 8 .....后面内容省略 BBED> set count 32 BBED> set offset 399 BBED> d Block: 4572 Offsets: 6389 to 6900 Dba:0x00000000 ------------------------------------------------------------------------ 2cc30323 390b2203 c20b2201 80195359 535f4c4f 42303030 30303031 30333043 BBED> set offset +3 BBED> d Block: 4572 Offsets: 6392 to 6903 Dba:0x00000000 ------------------------------------------------------------------------ 23390b22 03c20b22 01801953 59535f4c 4f423030 30303030 31303330 43303030 BBED> m /x 2341 --把其中的c3032339 改成c3032341 BBED> p *kdbr[22] BBED> x /rnnncnnncc --验证已修改 BBED> sum apply 有多少行不一致,就改多少行,再把system文件拷贝回去,打开数据库,可以正常创建对象了。
最后修改时间:2020-02-03 08:16:23
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论