这个例子并没有什么实际意义,只是我在了解block结构的过程中顺便做的一个例子。
用好BBED最关键的就是要了解block的结构,一个0x06的block大致有如下结构:
kcbh {
ub1 type_kcbh;
ub1 frmt_kcbh;
ub1 spare1_kcbh;
ub1 spare2_kcbh;
krdba rdba_kcbh;
ub4 bas_kcbh; /* base of SCN */
ub2 wrp_kcbh; /* wrap of SCN */
ub1 seq_kcbh; /* seq# of changes at same scn, KCBH_NLCSEQ */
ub1 flg_kcbh; /* see KCBHFNEW etc below */
ub2 chkval_kcbh;
ub2 spare3_kcbh;
}
ktbbh { /* 10201 struct ktbbh block header */
ub1 ktbbhtyp; /* block type */
ub4 ktbbhsid;
kscn ktbbhcsc; /* effective time of last cleanout */
b2 ktbbhict; /* number of itl entries mask 0x00ff*/
ub1 ktbbhflg; /* flags */
ub1 ktbbhfsl; /* free space lock */
krdba ktbbhfnx; /* next block in free list */
}
ktbit {
kxid ktbitxid; /* transaction id */
kuba ktbituba; /* undo address for last change */
b2 ktbitflg; /* num of locks in block */
ktbitun_t _ktbitun;
ub4 ktbitbas; /* sys commit num base */
}
kdbh {
ub1 kdbhflag; /* FLAGs */
ktno kdbhntab; /* Number of TABles in the table index */
ub2 kdbhnrow; /* Number of ROWs in the row index */
sb2 kdbhfrre; /* first FRee Row index Entry */
sb2 kdbhfsbo; /* Free Space Beginning Offset */
sb2 kdbhfseo; /* Free Space Ending Offset */
b2 kdbhavsp; /* AVailable SPace in the block */
b2 kdbhtosp; /* TOtal Space that will be available */
}
kdbt {
b2 kdbtoffs; /* OFFSet in the block from kdbpri */
b2 kdbtnrow; /* Number of Rows in the table */
}
kdrh {
ub1 kdrhflag; /* the flag byte for the piece being inserte
ub1 kdrhlock; /* locking itl index */
ub1 kdrhccnt; /* the column count for the row piece */
}
SQL_astca>create table dras.t2(c1 number,c2 varchar2(5)) tablespace testtbs;
Table created.
SQL_astca>insert into dras.t2 values(1,'a');
1 row created.
SQL_astca>insert into dras.t2 values(2,'b');
1 row created.
SQL_astca>insert into dras.t2 values(3,'c');
1 row created.
SQL_astca>commit;
Commit complete.
SQL_astca>select tablespace_name,extent_management,SEGMENT_SPACE_MANAGEMENT from dba_tablespaces where tablespace_name='TESTTBS';
TABLESPACE_NAME EXTENT_MAN SEGMEN
------------------------------ ---------- ------
TESTTBS LOCAL MANUAL
SQL_astca>alter system checkpoint;
System altered.
SQL_astca>select FILE_ID,RELATIVE_FNO,BLOCK_ID from dba_extents where owner='DRAS' and segment_name='T2';
FILE_ID RELATIVE_FNO BLOCK_ID
---------- ------------ ----------
133 133 33
MSSM段头的下一个block就是数据块:
SQL_astca>ALTER SYSTEM DUMP DATAFILE 133 BLOCK 34;
System altered.
SQL_astca>oradebug setmypid
Statement processed.
SQL_astca>oradebug tracefile_name
/cadrasu01/app/oracle/admin/astca/udump/astca_ora_1060992.trc
上述trace file中有如下内容:
Start dump data blocks tsn: 84 file#: 133 minblk 34 maxblk 34
buffer tsn: 84 rdba: 0x21400022 (133/34)
scn: 0x0008.a9e7d1b7 seq: 0x01 flg: 0x06 tail: 0xd1b70601
frmt: 0x02 chkval: 0x39da type: 0x06=trans data
Block header dump: 0x21400022
Object id on Block? Y
seg/obj: 0x
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x
0x02 0x0000.000.00000000 0x0000
data_block_dump,data header at 0x
===============
tsiz: 0x1fa0
hsiz: 0x18
pbl: 0x
bdba: 0x21400022
76543210
flag=--------
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x
avsp=0x
tosp=0x
0xe:pti[0] nrow=3 offs=0
0x12:pri[0] offs=0x
0x14:pri[1] offs=0x
0x16:pri[2] offs=0x
block_row_dump:
tab 0, row 0, @0x
tl: 8 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 61
tab 0, row 1, @0x
tl: 8 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 62
tab 0, row 2, @0x
tl: 8 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 04
col 1: [ 1] 63
end_of_block_dump
End dump data blocks tsn: 84 file#: 133 minblk 34 maxblk 34
从上面可以看到,这里第二行的offset是0x1f90,这是一个相对地址,需要加上一个BASE,BASE的计算方法为:
对于ASSM:76+(itc-1)*24
对于MSSM:68+(itc-1)*24
所以我们这里BBED实际用到的offset为0x1f90+68+(2-1)*24=8172
好了,我们的准备工作已经就绪。
SQL_astca>select * from dras.t2;
C
---------- -----
2 b
现在我们来用BBED把上述第二条记录的C2的值由b改成d。
$ bbed parfile=par.bbd
Password:
BBED: Release
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
BBED> set file 133
FILE# 133
BBED> set block 34
BLOCK# 34
BBED> set offset 8172
OFFSET 8172
BBED> dump
File: /dras20/astca/test01.dbf (133)
Block: 34 Offsets: 8172 to 8191 Dba:0x21400022
------------------------------------------------------------------------
<32 bytes per line>
这里的2c0102是行头,就是我上面提到的kdrh,这里2c表示是行头的开始,01表示对应1号ITL,02表示这行有2个字段的值。
后面的02 c1030162就是我要修改的内容,02表示第一个字段的长度为2个byte,后面紧跟的c103就是这两个byte的具体值;后面紧跟着的01表示第二个字段的长度为1个byte,后面紧跟的62就是这个byte的具体值。
我们现在是想把t2中第二条记录的C2字段的值由b改成d,d所对应的存储格式为:
SQL> select dump('d',16) from dual;
DUMP('D',16)
----------------
Typ=96 Len=1: 64
所以这里我们只需要把62改成64就可以了。
BBED> set offset 8179
OFFSET 8179
BBED> dump
File: /dras20/astca/test01.dbf (133)
Block: 34 Offsets: 8179 to 8191 Dba:0x21400022
------------------------------------------------------------------------
<32 bytes per line>
BBED> modify /x 0x64
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /dras20/astca/test01.dbf (133)
Block: 34 Offsets: 8179 to 8191 Dba:0x21400022
------------------------------------------------------------------------
<32 bytes per line>
BBED> sum apply
Check value for File 133, Block 34:
current = 0x39dc, required = 0x39dc
好了,现在我们已经改完了,最后我们来看一下改过之后的效果:
BBED> exit
$ sqlplus '/ as sysdba';
SQL*Plus: Release
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to an idle instance.
SQL_astca>startup
ORACLE instance started.
Total System Global Area 824150304 bytes
Fixed Size 743712 bytes
Variable Size 285212672 bytes
Database Buffers 536870912 bytes
Redo Buffers 1323008 bytes
Database mounted.
Database opened.
SQL_astca>select * from dras.t2;
C
---------- -----
2 d
Ive been researching this and I'll have to agree