合 Oracle异常恢复BBED系列
Tags: Oracle编译恢复BBEDsys.bootstrap$ORA-08102
BBED模拟并修复ORA-08102错误
前言部分
导读和注意事项
各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~:
① 使用BBED修复ORA-08102错误(重点)
② BBED的使用
③ 数据块格式的dump文件解释
④ ORA-08102错误的trace文件解释
⑤ 从rdba获取ROWID信息
⑥ 其它实用技能
本文简介
这几天一个朋友问我有关ORA-08102的错误,而且是关于OBJ$表上的I_OBJ4索引。这些系统对象的索引,不能采用重建或设置事件的方式来修复该错误。模模糊糊的记得很早以前看过使用BBED的方式来修复该错误,只是已经记不清了。正好,趁此机会把该错误再模拟的复现一下,也把bbed再熟悉一下吧。
朋友发给我的参考文章也是大师惜分飞的博客地址,大致看了一下过程,主要是找到索引块的相关地址,然后利用bbed把键值修改的和表中存储的一致即可。还是那句话,“纸上得来终觉浅,绝知此事要躬行。”,自己模拟实验,这个过程是必须的。
废话不多说,开始实验吧。
相关文章链接
阅读本篇文章,请先阅读以下内容:
- Oracle 中 Object_iD 和 Data_Object_ID 的区别:http://blog.itpub.net/26736162/viewspace-2145230/
- Oracle的dump函数:http://blog.itpub.net/26736162/viewspace-2145228/
注意事项
- bbed毕竟是未公开的恢复方式,所以不熟悉的朋友要慎用。
- startup force慎用
- 操作bbed之前最好先把数据库关闭
相关知识点扫盲
An ORA-08102 indicates that there is a mismatch between the key(s) stored in the index and the values stored in the table.What typically happens in the index is built and at some future time,some type of corruption occurs,either in the table or index,to cause the mismatch.
ORA-08102常见于索引键值与表上存的值不一致。
1 2 3 4 5 | [oracle@rhel6lhr ~]$ oerr ora 8102 08102, 00000, "index key not found, obj# %s, file %s, block %s (%s)" // *Cause: Internal error: possible inconsistency in index // *Action: Send trace file to your customer support representative, along // with information on reproducing the error |
ora-08102这种错误说明索引或表出现了数据不一致,索引上记录的键值和表里的数据不一致,引起访问失败,一般重建下索引就可以解决。两边不一致改表和索引都能达到目的,只要一致即可,但有一个原则就是索引键值始终要保证按顺序递增。通常有三种情况:
1.如果损坏为索引,则删除索引并重建索引,但对于index的obj#小于56的情况,由于是核心的bootstrap$对象,index是在DB启动时由DB自动创建,此种情况下通过设置event 38003或startup migrate模式都不能解决,但obj#>56的则可以。
2.如果损坏为块级别,则采用坏块的处理方法
3.如果损坏的为表的记录级别的则采用bbed或其它工具
I_OBJ1、I_OBJ2、I_OBJ3、I_OBJ4、I_OBJ5这几个都是OBJ$基表的索引,如果损坏会非常麻烦,因为ORACLE 对这些对象的DDL做了严格限制,没有办法简单修复它们。
1 2 3 4 5 6 | SYS@ora11g > drop index i_obj4; drop index i_obj5 * ERROR at line 1: ORA-00701: object necessary for warmstarting database cannot be altered |
实验环境介绍
项目 | source db |
---|---|
db 类型 | 单机 |
db version | 11.2.0.3.0 |
db 存储 | FS |
OS版本及kernel版本 | RHEL 6.5 |
实验目标
实验目标:使用BBED模拟并修复ORA-08102错误。
模拟错误过程:通过bbed修改OBJ$表中DATAOBJ#列最大的行所在的块,让DATAOBJ#的值增大,从而和索引中记录的值不一致。重启数据库并创建表让数据库报出ORA-08102错误。
修复错误过程:通过bbed把表中或索引中的不一致的数据修改成一致的,从而修复ORA-08102错误。
实验过程
做全备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | [oracle@rhel6lhr ~]$ more rman_full.sh rman target / nocatalog <<EOF run{ backup database format '/home/oracle/bak/%d_%U.full'; sql 'alter system archive log current'; backup archivelog all format '/home/oracle/bak/%d_%U.arc'; backup current controlfile format '/home/oracle/bak/%d_%U.ctl'; } EOF [oracle@rhel6lhr ~]$ sh rman_full.sh Recovery Manager: Release 11.2.0.3.0 - Production on Wed Sep 20 13:56:41 2017 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved. connected to target database: ORA11G (DBID=4270446895) using target database control file instead of recovery catalog RMAN> 2> 3> 4> 5> 6> Starting backup at 2017-09-20 13:56:41 allocated channel: ORA_DISK_1 channel ORA_DISK_1: SID=21 device type=DISK channel ORA_DISK_1: starting full datafile backup set channel ORA_DISK_1: specifying datafile(s) in backup set input datafile file number=00004 name=/u01/app/oracle/oradata/ora11g/users01.dbf input datafile file number=00001 name=/u01/app/oracle/oradata/ora11g/system01.dbf input datafile file number=00002 name=/u01/app/oracle/oradata/ora11g/sysaux01.dbf input datafile file number=00005 name=/u01/app/oracle/oradata/ora11g/example01.dbf input datafile file number=00003 name=/u01/app/oracle/oradata/ora11g/undotbs01.dbf input datafile file number=00022 name=/u01/app/oracle/oradata/ora11g/ts_ogg01.dbf input datafile file number=00007 name=/u01/app/oracle/oradata/ora11g/DWII_CNY_BK_F_01.dbf input datafile file number=00008 name=/u01/app/oracle/oradata/ora11g/DWII_DPA_F_01.dbf input datafile file number=00009 name=/u01/app/oracle/oradata/ora11g/DWII_DPA_I_01.dbf input datafile file number=00010 name=/u01/app/oracle/oradata/ora11g/DWII_DPA_S_01.dbf input datafile file number=00011 name=/u01/app/oracle/oradata/ora11g/DWII_SOR_F_01.dbf input datafile file number=00012 name=/u01/app/oracle/oradata/ora11g/DWII_SOR_I_01.dbf input datafile file number=00013 name=/u01/app/oracle/oradata/ora11g/DW_USER.dbf input datafile file number=00014 name=/u01/app/oracle/oradata/ora11g/SQCHECK.dbf input datafile file number=00015 name=/u01/app/oracle/oradata/ora11g/SD_CNY_D_01.dbf input datafile file number=00016 name=/u01/app/oracle/oradata/ora11g/SD_CNY_F_01.dbf input datafile file number=00017 name=/u01/app/oracle/oradata/ora11g/SD_DPA_D_01.dbf input datafile file number=00018 name=/u01/app/oracle/oradata/ora11g/SD_DPA_F_01.dbf input datafile file number=00019 name=/u01/app/oracle/oradata/ora11g/SD_SORT_T_01.dbf input datafile file number=00020 name=/u01/app/oracle/oradata/ora11g/DWII_FXDM_F_01.dbf input datafile file number=00021 name=/u01/app/oracle/oradata/ora11g/SD_SOR_T_01.dbf input datafile file number=00006 name=/u01/app/oracle/oradata/ora11g/aa.dbf input datafile file number=00023 name=/u01/app/oracle/oradata/ora11g/test01.dbf channel ORA_DISK_1: starting piece 1 at 2017-09-20 13:56:42 channel ORA_DISK_1: finished piece 1 at 2017-09-20 13:59:17 piece handle=/home/oracle/bak/ORA11G_27seuekq_1_1.full tag=TAG20170920T135642 comment=NONE channel ORA_DISK_1: backup set complete, elapsed time: 00:02:35 Finished backup at 2017-09-20 13:59:17 Starting Control File and SPFILE Autobackup at 2017-09-20 13:59:17 piece handle=/u05/app/oracle/flash_recovery_area/ORA11G/autobackup/2017_09_20/o1_mf_s_955202357_dw40xohn_.bkp comment=NONE Finished Control File and SPFILE Autobackup at 2017-09-20 13:59:18 sql statement: alter system archive log current Starting backup at 2017-09-20 13:59:18 current log archived using channel ORA_DISK_1 channel ORA_DISK_1: starting archived log backup set channel ORA_DISK_1: specifying archived log(s) in backup set input archived log thread=1 sequence=302 RECID=304 STAMP=955202163 input archived log thread=1 sequence=303 RECID=305 STAMP=955202358 input archived log thread=1 sequence=304 RECID=306 STAMP=955202358 channel ORA_DISK_1: starting piece 1 at 2017-09-20 13:59:18 channel ORA_DISK_1: finished piece 1 at 2017-09-20 13:59:19 piece handle=/home/oracle/bak/ORA11G_29seuepm_1_1.arc tag=TAG20170920T135918 comment=NONE channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01 Finished backup at 2017-09-20 13:59:19 Starting backup at 2017-09-20 13:59:20 using channel ORA_DISK_1 channel ORA_DISK_1: starting full datafile backup set channel ORA_DISK_1: specifying datafile(s) in backup set including current control file in backup set channel ORA_DISK_1: starting piece 1 at 2017-09-20 13:59:21 channel ORA_DISK_1: finished piece 1 at 2017-09-20 13:59:22 piece handle=/home/oracle/bak/ORA11G_2aseuepo_1_1.ctl tag=TAG20170920T135920 comment=NONE channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01 Finished backup at 2017-09-20 13:59:22 Starting Control File and SPFILE Autobackup at 2017-09-20 13:59:22 piece handle=/u05/app/oracle/flash_recovery_area/ORA11G/autobackup/2017_09_20/o1_mf_s_955202362_dw40xtf0_.bkp comment=NONE Finished Control File and SPFILE Autobackup at 2017-09-20 13:59:23 RMAN> Recovery Manager complete. |
模拟一:BBED模拟ORA-08102错误
通过BBED修改OBJ$中DATAOBJ$重现I_OBJ4索引报ORA-08102错误。定位需要破坏的OBJ$上DATAOBJ$列最大的记录,使之和索引I_OBJ4中记录不一致,从而实现ORA-8102错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | [oracle@rhel6lhr ~]$ ORACLE_SID=ora11g [oracle@rhel6lhr ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.3.0 Production on Thu Sep 21 09:24:08 2017 Copyright (c) 1982, 2011, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SYS@ora11g > select object_id,object_type from dba_objects where object_name='I_OBJ4'; OBJECT_ID OBJECT_TYPE ---------- ------------------- 39 INDEX SYS@ora11g > select max(DATAOBJ#) from obj$; MAX(DATAOBJ#) ------------- 94098 SYS@ora11g > select dump(94098,16) from dual; DUMP(94098,16) ----------------------- Typ=2 Len=4: c3,a,29,63 ===>>>>> Typ=2表示NUMBER,96表示CHAR。Len=4表示4位长度,所以,94098在数据库内部的存储格式为04c30a2963 SYS@ora11g > SELECT DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) FILE#, 2 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) BLOCK#, 3 DBMS_ROWID.ROWID_ROW_NUMBER(ROWID) ROW# 4 FROM OBJ$ 5 WHERE DATAOBJ# = 94098; FILE# BLOCK# ROW# ---------- ---------- ---------- 1 241 27 SYS@ora11g > SELECT COUNT(*) COUNTS, 2 MAX(DBMS_ROWID.ROWID_ROW_NUMBER(ROWID)) MAX_ROWNUM, 3 MIN(DBMS_ROWID.ROWID_ROW_NUMBER(ROWID)) MIN_ROWNUM 4 FROM SYS.OBJ$ D 5 WHERE DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) = 1 6 AND DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) = 241; COUNTS MAX_ROWNUM MIN_ROWNUM ---------- ---------- ---------- 105 104 0 |
根据以上的SQL可以得到下表的内容:
项目 | 值 |
---|---|
OBJ$上DATAOBJ#列的最大值 | 94098 |
OBJ$上DATAOBJ#列的最大值dump值 | Typ=2 Len=4: c3,a,29,63 即:04c30a2963 |
该行所在数据块的地址 | FILE# BLOCK# ROW# ---------- ---------- ---------- 1 241 27 |
该行的存储情况 | COUNTS MAX_ROWNUM MIN_ROWNUM ---------- ---------- ---------- 105 104 0 |
即:OBJ$表上DATAOBJ#列的最大值为94098,该值在Oracle数据库中的存储格式为04c30a2963,该行数据所在的块为1号文件,241号块,第27行,该块上共有105行数据,最大值的行号为104,最小值的行号为0。
dump文件解析
先对1号文件,241号块做dump:
1 2 3 4 5 6 7 8 9 10 11 | SYS@ora11g > conn / as sysdba Connected. SYS@ora11g > alter system dump datafile 1 block 241; System altered. SYS@ora11g > select value from v$diag_info where name='Default Trace File'; VALUE -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/ora11g/ora11g/trace/ora11g_ora_28221.trc |
关于块格式的详细介绍请参考:<http://blog.itpub.net/26736162/viewspace-2141499/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | Start dump data blocks tsn: 0 file#:1 minblk 241 maxblk 241 ====>>>>> SYSTEM是0号表空间1号文件,当前块是241号 Block dump from cache:====>>>>> 从内存中dump出来的 Dump of buffer cache at level 4 for tsn=0 rdba=4194545====>>>>> cache中的位置 BH (0x6cfe2658) file#: 1 rdba: 0x004000f1 (1/241) class: 1 ba: 0x6cd1a000====>>>>> 参考链接地址 set: 5 pool: 3 bsz: 8192 bsi: 0 sflg: 1 pwc: 0,25 dbwrid: 0 obj: 18 objn: 18 tsn: 0 afn: 1 hint: f hash: [0x773fca58,0x773fca58] lru: [0x6dbedcf0,0x6bbf1e40] lru-flags: hot_buffer ckptq: [NULL] fileq: [NULL] objq: [0x6e7d8388,0x6d7e82d8] objaq: [0x6d3f0588,0x6d7e82e8] st: XCURRENT md: NULL fpin: 'kdswh05: kdsgrp' tch: 11 flags: LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [65535] Block dump from disk: ====>>>>> 参考链接地址 buffer tsn: 0 rdba: 0x004000f1 (1/241) scn: 0x0000.038f7e74 seq: 0x01 flg: 0x06 tail: 0x7e740601 frmt: 0x02 chkval: 0xc3cc type: 0x06=trans data Hex dump of block: st=0, typ_found=1 Dump of memory from 0x00007F1583F05A00 to 0x00007F1583F07A00 7F1583F05A00 0000A206 004000F1 038F7E74 06010000 [......@.t~......] 7F1583F05A10 0000C3CC 00000001 00000012 038F7E73 [............s~..] 7F1583F05A20 00000000 0002F801 00000000 00190006 [................] 7F1583F05A30 00000BF4 00C002D5 00030203 00002001 [............. ..] 7F1583F05A40 038F7E74 00690100 00E4FFFF 035F013B [t~....i.....;._.] ...........省略部分输出................ 7F1583F079C0 0215C102 800103C1 4F434905 C102244C [.........ICOL$..] 7F1583F079D0 C102FF02 6F780703 2F0A1109 6F78070E [......xo.../..xo] 7F1583F079E0 3B0A1109 6F780701 2F0A1109 02C1020E [...;..xo.../....] 7F1583F079F0 8001FFFF 028001FF 800102C1 7E740601 [..............t~] Block header dump: 0x004000f1 ====>>>>> 参考链接地址 Object id on Block? Y seg/obj: 0x12 csc: 0x00.38f7e73 itc: 1 flg: - typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0006.019.00000bf4 0x00c002d5.0203.03 --U- 1 fsc 0x0000.038f7e74 bdba: 0x004000f1 data_block_dump,data header at 0x7f1583f05a44 =============== tsiz: 0x1fb8 hsiz: 0xe4 pbl: 0x7f1583f05a44 76543210 flag=-------- ntab=1 nrow=105 ====>>>>> 共105行数据 frre=-1 fsbo=0xe4 fseo=0x13b avsp=0x35f tosp=0x35f 0xe:pti[0] nrow=105 offs=0 0x12:pri[0] offs=0x1f79 0x14:pri[1] offs=0x1f36 ...........省略部分输出................ 0x44:pri[25] offs=0x18ff 0x46:pri[26] offs=0x18c1 0x48:pri[27] offs=0x13b====>>>>> 第27行数据的指针偏移位置是13b,转换为10进制是315,selet to_number('13b','xxx') from dual; ...........省略部分输出................ 0xde:pri[102] offs=0x515 0xe0:pri[103] offs=0x4ce 0xe2:pri[104] offs=0x48b block_row_dump: tab 0, row 0, @0x1f79 tl: 63 fb: --H-FL-- lb: 0x0 cc: 18 col 0: [ 2] c1 15 col 1: [ 2] c1 03 col 2: [ 1] 80 col 3: [ 5] 49 43 4f 4c 24 col 4: [ 2] c1 02 col 5: *NULL* col 6: [ 2] c1 03 col 7: [ 7] 78 6f 09 11 0a 2f 0e col 8: [ 7] 78 6f 09 11 0a 3b 01 col 9: [ 7] 78 6f 09 11 0a 2f 0e col 10: [ 2] c1 02 col 11: *NULL* col 12: *NULL* col 13: [ 1] 80 col 14: *NULL* col 15: [ 1] 80 col 16: [ 2] c1 02 col 17: [ 1] 80 ...........省略部分输出................ tab 0, row 27, @0x13b ====>>>>> 该块中第一个表第27行的指针位置,转换为10进制是315 tl: 72 fb: --H-FL-- lb: 0x1 cc: 18 col 0: [ 2] c1 02 col 1: [ 4] c3 0a 29 63 col 2: [ 1] 80 col 3: [12] 5f 4e 45 58 54 5f 4f 42 4a 45 43 54 col 4: [ 2] c1 02 col 5: *NULL* col 6: [ 1] 80 col 7: [ 7] 78 6f 09 11 0a 2f 0e col 8: [ 7] 78 75 09 14 13 1d 25 col 9: [ 7] 78 6f 09 11 0a 2f 0e col 10: [ 1] 80 col 11: *NULL* col 12: *NULL* col 13: [ 1] 80 col 14: *NULL* col 15: [ 1] 80 col 16: [ 4] c3 07 38 24 col 17: [ 1] 80 ...........省略部分输出................ tab 0, row 104, @0x48b tl: 67 fb: --H-FL-- lb: 0x0 cc: 18 col 0: [ 3] c2 02 06 col 1: [ 3] c2 02 06 col 2: [ 1] 80 col 3: [ 7] 41 43 43 45 53 53 24 col 4: [ 2] c1 02 col 5: *NULL* col 6: [ 2] c1 03 col 7: [ 7] 78 6f 09 11 0a 2f 10 col 8: [ 7] 78 6f 09 11 0a 2f 10 col 9: [ 7] 78 6f 09 11 0a 2f 10 col 10: [ 2] c1 02 col 11: *NULL* col 12: *NULL* col 13: [ 1] 80 col 14: *NULL* col 15: [ 1] 80 col 16: [ 2] c1 02 col 17: [ 1] 80 end_of_block_dump End dump data blocks tsn: 0 file#: 1 minblk 241 maxblk 241 |
由于SYS.OBJ$表共21列,但是最后3列都为空,所以,dump文件里就没有显示出来。将该行数据以16进制dump出来看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | SELECT DUMP(OBJ#, 16), DUMP(DATAOBJ#, 16), DUMP(OWNER#, 16), DUMP(NAME, 16), DUMP(NAMESPACE, 16), DUMP(SUBNAME, 16), DUMP(TYPE#, 16), DUMP(CTIME, 16), DUMP(MTIME, 16), DUMP(STIME, 16), DUMP(STATUS, 16), DUMP(REMOTEOWNER, 16), DUMP(LINKNAME, 16), DUMP(FLAGS, 16), DUMP(OID$, 16), DUMP(SPARE1, 16), DUMP(SPARE2, 16), DUMP(SPARE3, 16), DUMP(SPARE4, 16), DUMP(SPARE5, 16), DUMP(SPARE6, 16) FROM SYS.OBJ$ D WHERE DATAOBJ# = 94098; |
结果和dump文件中的内容一致。
列名 | 10进制值 | 16进制值 | dump文件的存储 |
---|---|---|---|
OBJ# | 1 | Typ=2 Len=2: c1,2 | col 0: [ 2] c1 02 |
DATAOBJ# | 94098 | Typ=2 Len=4: c3,a,29,63 | col 1: [ 4] c3 0a 29 63 |
OWNER# | 0 | Typ=2 Len=1: 80 | col 2: [ 1] 80 |
NAME | _NEXT_OBJECT | Typ=1 Len=12: 5f,4e,45,58,54,5f,4f,42,4a,45,43,54 | col 3: [12] 5f 4e 45 58 54 5f 4f 42 4a 45 43 54 |
NAMESPACE | 1 | Typ=2 Len=2: c1,2 | col 4: [ 2] c1 02 |
SUBNAME | NULL | col 5: *NULL* | |
TYPE# | 0 | Typ=2 Len=1: 80 | col 6: [ 1] 80 |
CTIME | 2011-09-17 09:46:13 | Typ=12 Len=7: 78,6f,9,11,a,2f,e | col 7: [ 7] 78 6f 09 11 0a 2f 0e |
MTIME | 2017-09-20 18:28:36 | Typ=12 Len=7: 78,75,9,14,13,1d,25 | col 8: [ 7] 78 75 09 14 13 1d 25 |
STIME | 2011-09-17 09:46:13 | Typ=12 Len=7: 78,6f,9,11,a,2f,e | col 9: [ 7] 78 6f 09 11 0a 2f 0e |
STATUS | 0 | Typ=2 Len=1: 80 | col 10: [ 1] 80 |
REMOTEOWNER | NULL | col 11: *NULL* | |
LINKNAME | NULL | col 12: *NULL* | |
FLAGS | 0 | Typ=2 Len=1: 80 | col 13: [ 1] 80 |
OID$ | NULL | col 14: *NULL* | |
SPARE1 | 0 | Typ=2 Len=1: 80 | col 15: [ 1] 80 |
SPARE2 | 65535 | Typ=2 Len=4: c3,7,38,24 | col 16: [ 4] c3 07 38 24 |
SPARE3 | 0 | Typ=2 Len=1: 80 | col 17: [ 1] 80 |
所以,从dump文件中还可以得到第27行数据的指针偏移位置是13b,转换为10进制是315。
使用bbed破坏该块中的第27行数据
使用bbed破坏记录,修改dataobj#中的值,使得obj$.dataobj#和i_obj4中的dataobj#不匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | SYS@ora11g > select name from v$datafile where file#=1; NAME -------------------------------------------------------------------------------- /u01/app/oracle/oradata/ora11g/system01.dbf -- 最好是干净的关闭数据库 [oracle@rhel6lhr ~]$ bbed password=blockedit blocksize=8192 mode=edit filename='/u01/app/oracle/oradata/ora11g/system01.dbf' BBED: Release 2.0.0.0.0 - Limited Production on Thu Sep 21 10:40:47 2017 Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved. ************* !!! For Oracle Internal Use only !!! *************** BBED> show all FILE# 0 BLOCK# 1 OFFSET 0 DBA 0x00000000 (0 0,1) FILENAME /u01/app/oracle/oradata/ora11g/system01.dbf BIFILE bifile.bbd LISTFILE BLOCKSIZE 8192 MODE Edit EDIT Unrecoverable IBASE Dec OBASE Dec WIDTH 80 COUNT 512 LOGFILE ./log.bbd SPOOL No BBED> set block 241 BLOCK# 241 BBED> map File: /u01/app/oracle/oradata/ora11g/system01.dbf (0) Block: 241 Dba:0x00000000 ------------------------------------------------------------ KTB Data Block (Table/Cluster) ====>>>>> 表明是数据块 struct kcbh, 20 bytes @0 struct ktbbh, 48 bytes @20 struct kdbh, 14 bytes @68 struct kdbt[1], 4 bytes @82 sb2 kdbr[105] @86 ub1 freespace[87] @296 ub1 rowdata[7805] @383 ub4 tailchk @8188 ====>>>>> 块校验位 BBED> p kdbr===>>>>> 块中数据指针位置 sb2 kdbr[0] @86 8057 sb2 kdbr[1] @88 7990 sb2 kdbr[2] @90 7928 。。。。。。。。。。。省略。。。。。。。。。。。 sb2 kdbr[24] @134 6466 sb2 kdbr[25] @136 6399 sb2 kdbr[26] @138 6337 sb2 kdbr[27] @140 315===>>>>> 第27行数据指针位置为315,和dump出来的信息一致 sb2 kdbr[28] @142 6268 sb2 kdbr[29] @144 6201 。。。。。。。。。。。省略。。。。。。。。。。。 sb2 kdbr[103] @292 1230 sb2 kdbr[104] @294 1163===>>>>> 表明该块共有105行数据 BBED> p *kdbr[27] rowdata[0] ---------- ub1 rowdata[0] @383 0x2c===>>>>> 第27行偏移位置为383 BBED> show offset OFFSET 383 BBED> x /rnnncncntttnccncnnn===>>>>> 打印第27行的数据内容,n代表number,c代表char,t代表date rowdata[0] @383 ---------- flag@383: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@384: 0x01 cols@385: 18===>>>>> 共18列 col 0[2] @386: 1 col 1[4] @389: 94098 ==>>>>> 需要修改该列的值 col 2[1] @394: 0 col 3[12] @396: _NEXT_OBJECT col 4[2] @409: 1 col 5[0] @412: *NULL* col 6[1] @413: 0 col 7[7] @415: 2011-09-17 09:46:13 col 8[7] @423: 2017-09-20 18:28:36 col 9[7] @431: 2011-09-17 09:46:13 col 10[1] @439: 0 col 11[0] @441: *NULL* col 12[0] @442: *NULL* col 13[1] @443: 0 col 14[0] @445: *NULL* col 15[1] @446: 0 col 16[4] @448: 65535 col 17[1] @453: 0 BBED> set offset 389 OFFSET 389 BBED> d /v count 32 File: /u01/app/oracle/oradata/ora11g/system01.dbf (0) Block: 241 Offsets: 389 to 420 Dba:0x00000000 ------------------------------------------------------- 04c30a29 6301800c 5f4e4558 545f4f42 l ...)c..._NEXT_OB 4a454354 02c102ff 01800778 6f09110a l JECT.......xo... <16 bytes per line> BBED> |
当然,也可以使用find来直接查询:
1 2 3 4 5 6 7 8 9 10 11 | BBED> f /x c30a29 File: /u01/app/oracle/oradata/ora11g/system01.dbf (0) Block: 241 Offsets: 390 to 421 Dba:0x00000000 ------------------------------------------------------------------------ c30a2963 01800c5f 4e455854 5f4f424a 45435402 c102ff01 8007786f 09110a2f <32 bytes per line> BBED> f BBED-00212: search string not found |
94098和94099对应的存储格式:
1 2 3 4 5 6 | SYS@ora11g > select dump(94098,16),dump(94099,16) from dual; DUMP(94098,16) DUMP(94099,16) ----------------------- ----------------------- Typ=2 Len=4: c3,a,29,63 Typ=2 Len=4: c3,a,29,64 |
使用bbed 修改04c30a2963为04c30a2964,即把94098修改为94099,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | BBED> set offset +2 OFFSET 392 BBED> d File: /u01/app/oracle/oradata/ora11g/system01.dbf (0) Block: 241 Offsets: 392 to 423 Dba:0x00000000 ------------------------------------------------------------------------ 29630180 0c5f4e45 58545f4f 424a4543 5402c102 ff018007 786f0911 0a2f0e07 <32 bytes per line> BBED> m /x 2964 Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) Y File: /u01/app/oracle/oradata/ora11g/system01.dbf (0) Block: 241 Offsets: 392 to 423 Dba:0x00000000 ------------------------------------------------------------------------ 29640180 0c5f4e45 58545f4f 424a4543 5402c102 ff018007 786f0911 0a2f0e07 <32 bytes per line> BBED> d /v File: /u01/app/oracle/oradata/ora11g/system01.dbf (0) Block: 241 Offsets: 392 to 423 Dba:0x00000000 ------------------------------------------------------- 29640180 0c5f4e45 58545f4f 424a4543 l )d..._NEXT_OBJEC 5402c102 ff018007 786f0911 0a2f0e07 l T.......xo.../.. <16 bytes per line> BBED> sum Check value for File 0, Block 241: current = 0xc3cc, required = 0xc4cc BBED> sum apply Check value for File 0, Block 241: current = 0xc4cc, required = 0xc4cc BBED> v DBVERIFY - Verification starting FILE = /u01/app/oracle/oradata/ora11g/system01.dbf BLOCK = 241 DBVERIFY - Verification complete Total Blocks Examined : 1 Total Blocks Processed (Data) : 1 Total Blocks Failing (Data) : 0 Total Blocks Processed (Index): 0 Total Blocks Failing (Index): 0 Total Blocks Empty : 0 Total Blocks Marked Corrupt : 0 Total Blocks Influx : 0 Message 531 not found; product=RDBMS; facility=BBED |
修改后查看该行记录的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | BBED> set offset 383 OFFSET 383 BBED> x /rnnncncntttnccncnnn rowdata[0] @383 ---------- flag@383: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@384: 0x01 cols@385: 18 col 0[2] @386: 1 col 1[4] @389: 94099 ==>>>>> 已修改 col 2[1] @394: 0 col 3[12] @396: _NEXT_OBJECT col 4[2] @409: 1 col 5[0] @412: *NULL* col 6[1] @413: 0 col 7[7] @415: 2011-09-17 09:46:13 col 8[7] @423: 2017-09-20 18:28:36 col 9[7] @431: 2011-09-17 09:46:13 col 10[1] @439: 0 col 11[0] @441: *NULL* col 12[0] @442: *NULL* col 13[1] @443: 0 col 14[0] @445: *NULL* col 15[1] @446: 0 col 16[4] @448: 65535 col 17[1] @453: 0 |
可以看到成功的将94098修改为94099。