【Oracle坏块】BBED参数介绍(二)
4、Map
Map会通过偏移量来显示block里的详细信息,如block header,data block header 和row directory。使用/v 选项,可以查看更详细的信息。
在不指定block的情况下,会显示当前block的信息,如果想显示其他block的信息,可以使用file name,file id,block 和DBA 来指定要显示的block。
BBED> map File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116538 Dba:0x0041c73a ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 96 bytes @20 struct kdbh, 14 bytes @116 struct kdbt[1], 4 bytes @130 sb2 kdbr[65] @134 ub1 freespace[857] @264 ub1 rowdata[7067] @1121 ub4 tailchk @8188
------这个是默认情况,@后边表示的是对应信息在block里的偏移量,即offset。
------通过dba来指定某个block
BBED> map /v dba 1,116538 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116538 Dba:0x0041c73a ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 ub1 type_kcbh @0 ub1 frmt_kcbh @1 ub2 wrp2_kcbh @2 ub4 rdba_kcbh @4 ub4 bas_kcbh @8 ub2 wrp_kcbh @12 ub1 seq_kcbh @14 ub1 flg_kcbh @15 ub2 chkval_kcbh @16 ub2 spare3_kcbh @18 struct ktbbh, 96 bytes @20 ub1 ktbbhtyp @20 union ktbbhsid, 4 bytes @24 struct ktbbhcsc, 8 bytes @28 sb2 ktbbhict @36 ub1 ktbbhflg @38 ub1 ktbbhfsl @39 ub4 ktbbhfnx @40 struct ktbbhitl[3], 72 bytes @44 struct kdbh, 14 bytes @116 ub1 kdbhflag @116 sb1 kdbhntab @117 sb2 kdbhnrow @118 sb2 kdbhfrre @120 sb2 kdbhfsbo @122 sb2 kdbhfseo @124 sb2 kdbhavsp @126 sb2 kdbhtosp @128 struct kdbt[1], 4 bytes @130 sb2 kdbtoffs @130 sb2 kdbtnrow @132 sb2 kdbr[65] @134 ub1 freespace[857] @264 ub1 rowdata[7067] @1121 ub4 tailchk @8188
------通过block来map
BBED> map block 116538 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116538 Dba:0x0041c73a ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 struct ktbbh, 96 bytes @20 struct kdbh, 14 bytes @116 struct kdbt[1], 4 bytes @130 sb2 kdbr[65] @134 ub1 freespace[857] @264 ub1 rowdata[7067] @1121 ub4 tailchk @8188
Map显示的具体信息解释如下:
------不同的block 可以第一个byte的值是不一样的。 具体值对应block 类型如下:
oracleblocks 的最后4个bytes 是tail check。看一下oracle 9i block的tail check 组成。
Oracleblock tail 由4个bytes组成,但实际上只用了低2个bytes来存放。 2个bytes的tail 由scn base,block type 和 scn sequence 组成。
------例如,如果SCN基号为0x00029728,块类型为06,SCN序列号为0x02,则尾部检查将为0x97280602 SCN base Type SCN seq ---------- ------ --------- 9728 06 02
虽然tail check 由3个部分组成,但是oracle 把这3部分作为一个整体来存储,并且占用4个bytes。
对于little-endian(低端)架构的机器,包括Intel, 他们会先存放low-order byte,即低位字节。
可以通过标准block editor 或者dump 来查看tail check。 对于不同的机器,他们存储的顺序是不一样的。比如tail check 0x97280602 在Intel Machine 就被存储为02062897,因为它会先保存low-order bytes。
5、dump
dump命令可以将block的内容显示到屏幕。每次显示的bytes由count控制,默认是512bytes。使用/v选项,可以显示更多详细信息。
示例:
BBED> dump /v dba 1,116538 offset 0 count 128 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116538 Offsets: 0 to 127 Dba:0x0041c73a ------------------------------------------------------- 06a20000 3ac74100 23912c00 00000204 l .¢..:Ɓ.#.,..... b79d0000 01000000 b4220100 1f912c00 l ·.......´"....,. 00800000 03000200 00000000 ffff0000 l ................ 00000000 00000000 00000000 00800080 l ................ 1f912c00 00000000 00000000 00000000 l ..,............. 00000000 00000000 00000000 00000000 l ................ 00000000 00000000 00000000 00000000 l ................ 00000000 00014100 ffff9400 ed035903 l ......A.....뭙. <16 bytes per line>
看一下blockheader 中第一行16个bytes 的架构:
Type | Format | Unused | RDBA | SCN Base | SCN Wrap | Seq | Flag |
06 | a2 | 0000 | 3ac74100 | 23912c00 | 0000 | 02 | 04 |
6、print命令
print命令输出data structures。在使用print时,可以指定dba,block 等参数来限定输出特定block。
在map章节讲了block结构,可以通过dump来查看block的type,现在通过print也可以查看
BBED> set dba 1,116538 DBA 0x0041c73a (4310842 1,116538) BBED> set offset 0 OFFSET 0 BBED> print kcbh.type_kcbh ub1 type_kcbh @0 0x06
--------可以通过print 输出指定名称的block structures
BBED> print kcbh struct kcbh, 20 bytes @0 ub1 type_kcbh @0 0x06 ub1 frmt_kcbh @1 0xa2 ub2 wrp2_kcbh @2 0x0000 ub4 rdba_kcbh @4 0x0041c73a ub4 bas_kcbh @8 0x002c9123 ub2 wrp_kcbh @12 0x0000 ub1 seq_kcbh @14 0x02 ub1 flg_kcbh @15 0x04 (KCBHFCKV) ub2 chkval_kcbh @16 0x9db7 ub2 spare3_kcbh @18 0x0000
------如果我们想确定block 中row的数量,可以print data header structure 或者kdbh
BBED> p kdbh struct kdbh, 14 bytes @116 ub1 kdbhflag @116 0x00 (NONE) sb1 kdbhntab @117 1 sb2 kdbhnrow @118 65 sb2 kdbhfrre @120 -1 sb2 kdbhfsbo @122 148 sb2 kdbhfseo @124 1005 sb2 kdbhavsp @126 857 sb2 kdbhtosp @128 857
------也可以指定某个具体的structure元素进行print
BBED> p kdbhnrow sb2 kdbhnrow @118 65 ------该block中保存了65行
注意:
当print 一个data structure 时,输出的格式如下:
UnitSize* | Name | Offset | Value
BBED> p kdbr sb2 kdbr[0] @134 7967 sb2 kdbr[1] @136 7846 sb2 kdbr[2] @138 7741 sb2 kdbr[3] @140 7620 ... sb2 kdbr[63] @260 1102 sb2 kdbr[64] @262 1005
格式对应关系:
UnitSize* | Name | Offset | Value |
sb2 | kdbr[0] | @134 | 7967 |
从上面的结果,可以看出,在这个数据块里有64行记录。 每行的pointer需要2个bytes来存储。 这64行row的offset 从134到262
------在pointer 加前缀* 可以print location data structure。可以使用kdbr[0] 作为一个指针来print 它对应的内容。这个kdbr[0] 是一个本地的data structure,print需要加*号前缀
BBED> p *kdbr[0] rowdata[6962] ------------- ub1 rowdata[6962] @8083 0x2c
通过这个信息,可以知道该行记录的偏移量是8083. dump它的具体信息
BBED> d /v dba 1,116538 offset 8083 count 128 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116538 Offsets: 8083 to 8191 Dba:0x0041c73a ------------------------------------------------------- 2c001603 53595311 495f4848 5f4f424a l ,...SYS.I_HH_OBJ 235f494e 54434f4c 23ff02c1 4702c147 l #_INTCOL#... 05494e44 45580778 77041101 39100778 l .INDEX.xw...9..x 77041101 39101332 3031392d 30342d31 l w...9..2019-04-1 373a3030 3a35363a 31350556 414c4944 l 7:00:56:15.VALID 014e014e 014e02c1 05ff044e 4f4e45ff l .N.N.N...NONE. 0159014e ff014e01 4e020623 91 l .Y.N..N.N..#. <16 bytes per line>
print命令也可以直接输出一个绝对的offset内容
BBED> p offset 8083 rowdata[6962] ------------- ub1 rowdata[6962] @8083 0x2c
------这个输出结果默认是16进制的。我们可以将其修改成其他格式
Switch | Display Format |
/x | Hex |
/d | signed decimal |
/u | unsigned decimal |
/o | Octal |
/c | Character |
/n | Oracle Number |
/t | Oracle Date |
/i | Oracle ROWID |
BBED> p offset 8083 rowdata[6962] ------------- ub1 rowdata[6962] @8083 0x2c BBED> p /d offset 8083 rowdata[6962] ------------- ub1 rowdata[6962] @8083 44
7、examine
examine命令也是用来显示datablock内容的,并且能对data structires进行一个解释说明
examine命令将根据以下参数解释块中的数据:
Switch | Display Format |
/b | b1,ub1(bytes) |
/h | b2,ub2(half-word) |
/w | b4,ub4(word) |
/l | b8,ub8(long)(was b4/ub4 in Oracle7) |
/r | Oracle table/index row |
examine可以根据switch的方式和print 命令进行一个结合来对data 进行解释说明
BBED> x /rcnn
examine命令也可以指定多行进行显示。下面的示例通过print命令将offset 指向到最后一个位置。然后repeat 3次
BBED> p kdbhnrow sb2 kdbhnrow @118 65 --这个block上共有65行 BBED> p *kdbr[64] rowdata[0] ---------- ub1 rowdata[0] @1121 0x2c --指向最后一行 BBED> x /3rcnn rowdata[0] @1121 ---------- flag@1121: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@1122: 0x00 cols@1123: 22 col 0[3] @1124: SYS col 1[8] @1128: ######################################### col 2[0] @1137: *NULL* col 3[3] @1138: 134 col 4[0] @1142: *NULL* col 5[7] @1143: ######################################### col 6[7] @1151: ######################################### col 7[7] @1159: ######################################### col 8[19] @1167: ######################################### col 9[5] @1187: ######################################### col 10[1] @1193: ######################################### col 11[1] @1195: ######################################### col 12[1] @1197: ######################################### col 13[2] @1199: 64 col 14[0] @1202: *NULL* col 15[4] @1203: ######################################### col 16[0] @1208: *NULL* col 17[1] @1209: ######################################### col 18[1] @1211: ######################################### col 19[0] @1213: *NULL* col 20[1] @1214: ######################################### col 21[1] @1216: ######################################### rowdata[97] @1218 ----------- flag@1218: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@1219: 0x00 cols@1220: 22 col 0[3] @1221: SYS col 1[17] @1225: ######################################### col 2[0] @1243: *NULL* col 3[3] @1244: 133 col 4[3] @1248: 133 col 5[5] @1252: ######################################### col 6[7] @1258: ######################################### col 7[7] @1266: ######################################### col 8[19] @1274: ######################################### col 9[5] @1294: ######################################### col 10[1] @1300: ######################################### col 11[1] @1302: ######################################### col 12[1] @1304: ######################################### col 13[2] @1306: 4 col 14[0] @1309: *NULL* col 15[4] @1310: ######################################### col 16[0] @1315: *NULL* col 17[1] @1316: ######################################### col 18[1] @1318: ######################################### col 19[0] @1320: *NULL* col 20[1] @1321: ######################################### col 21[1] @1323: ######################################### rowdata[204] @1325 ------------ flag@1325: 0x2c (KDRHFL, KDRHFF, KDRHFH) lock@1326: 0x00 cols@1327: 22 col 0[3] @1328: SYS col 1[16] @1332: ######################################### col 2[0] @1349: *NULL* col 3[3] @1350: 132 col 4[3] @1354: 132 col 5[5] @1358: ######################################### col 6[7] @1364: ######################################### col 7[7] @1372: ######################################### col 8[19] @1380: ######################################### col 9[5] @1400: ######################################### col 10[1] @1406: ######################################### col 11[1] @1408: ######################################### col 12[1] @1410: ######################################### col 13[2] @1412: 1 col 14[0] @1415: *NULL* col 15[13] @1416: ######################################### col 16[0] @1430: *NULL* col 17[1] @1431: ######################################### col 18[1] @1433: ######################################### col 19[14] @1435: ######################################### col 20[1] @1450: ######################################### col 21[1] @1452: ######################################### --examine显示3次
Oracle使用block 是从底向上的。 如果讲offset 设置为0. 那么将会组织repeat 的操作。
假如当前current row 是3,repeat 2次,那么row 3 和row 2 将被显示。 如果current row 是9, repeat 3次,那么row 9,row 8 和row 7 将被显示。
如果不能满足repeat,就会返回错误。
8、find命令
find命令可以用来搜索关键字。 可以从offset 0 搜索到top 或者从当前的offset 搜索到top。
find 命令支持的switch 类型如下,注意,find 不支持number和Date。
Switch | Datatype |
/x | Hexadecimal |
/d | Decimal |
/u | unsigned decimal |
/o | Octal |
/c | character(native) |
创建测试数据
SQL> drop table test; Table dropped. SQL> create table test(name varchar2(100)); Table created. SQL> insert into test values('ZhangSan'); 1 row created. SQL> commit; Commit complete.
查看block情况:
SQL> select rowid,dbms_rowid.rowid_relative_fno(rowid) rel_fno,dbms_rowid.rowid_block_number(rowid) blockno,dbms_rowid.rowid_row_number(rowid) rowno from test; ROWID REL_FNO BLOCKNO ROWNO ------------------ ---------- ---------- ---------- AAASK1AABAAAcc5AAA 1 116537 0
设置block 和 offset
BBED> set file 1 FILE# 1 BBED> set block 116537 BLOCK# 116537 BBED> set offset 0 OFFSET 0
查找ZhangSan
BBED> find /c ZhangSan top File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116537 Offsets: 8180 to 8191 Dba:0x0041c739 ------------------------------------------------------------------------ 5a68616e 6753616e 0506b2b2 <32 bytes per line>
BBED显示在offset8180的位置,dump该offset看看
BBED> d /v dba 1,116537 offset 8180 count 128 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116537 Offsets: 8180 to 8191 Dba:0x0041c739 ------------------------------------------------------- 5a68616e 6753616e 0506b2b2 l ZhangSan..²² <16 bytes per line>
如果我们要继续搜索Dave,那么只需要按下f 就可以了,不需要跟参数。
9、Copy命令
命令格式如下:
BBED> copy dba 1,116537 to dba 1,116538
这个命令很危险,慎用
10、modify命令
在file 1,block 116537有ZhangSan,把他改成LiSi
BBED> modify /c LiSi dba 1,116537 offset 8180 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116537 Offsets: 8180 to 8191 Dba:0x0041c739 ------------------------------------------------------------------------ 4c695369 6753616e 0506b2b2 <32 bytes per line>
dump验证一下
BBED> d /v dba 1,116537 offset 8180 count 128 File: /u01/app/oracle/oradata/T1/system01.dbf (1) Block: 116537 Offsets: 8180 to 8191 Dba:0x0041c739 ------------------------------------------------------- 4c695369 6753616e 0506b2b2 l LiSigSan..²² <16 bytes per line>
------注意:折里只修改了ZhangSan的前四个字母,即把Zhan改成LiSi
------注意:这里仅仅是修改,还没有进行update,即sum apply,select 才会改变。
SQL> select * from test; NAME ------------- ZhangSan
执行sum apply
BBED> sum apply Check value for File 1, Block 116537: current = 0x281a, required = 0x281a
再次查询
SQL> select * from test; NAME ----------- LiSigSan
未完待续.......