BBED(block browser and editor)是Oracle的一个使用工具,可以使用它来研究oracle block的结构,修改数据块的结构来完成特殊场景下的修复,在oracle10g下可以编译生成,如下:
[oracle@hadoop1 lib]$ pwd
/u02/app/oracle/product/10.2/db_1/rdbms/lib
[oracle@hadoop1 lib]$ make-f ins_rdbms.mk \
$ORACLE_HOME/rdbms/lib/bbed
[oracle@hadoop1 lib]$ ls-ltrh | grep bbed
-rwxr-xr-x1 oracle oinstall 691K 08-09 13:46 bbed
此时在当前目录下就会生成bbed可执行文件
[oracle@hadoop1 lib]$./bbed
Password:blockedit
BBED:Release 2.0.0.0.0 - Limited Production on чǚһ 8Ղ 12 10:33:09 2013
Copyright(c) 1982, 2007, Oracle. All rights reserved.
*************!!! For Oracle Internal Use only !!! ***************
BBED>show all;
FILE# 0
BLOCK# 1
OFFSET 0
DBA 0x00000000(0 0,1)
FILENAME
BIFILE bifile.bbd
LISTFILE
BLOCKSIZE 8192
MODE Browse
EDIT Unrecoverable
IBASE Dec
OBASE Dec
WIDTH 80
COUNT 512
LOGFILE log.bbd
SPOOL No
内部的命令不算多,也比较好理解,但如果用它来完成实际工作的话,需要对块结构有所了解后才能实施,毕竟他只是个工具而已,下面是一个修改行数据的小例子,没什么使用价值,主要是为了记录工具的基本用法。
1、 创建示例表并插入一下数据,然后刷新BUFFERCACHE,让数据落到磁盘上
SQL> create table t(msgvarchar(20),id int) tablespace users;
Tablecreated.
SQL> insert into tvalues('aaa',1);
1row created.
SQL> insert into tvalues('bbb',2);
1row created.
SQL> insert into tvalues('ccc',3);
1row created.
SQL> commit;
Commitcomplete.
SQL> alter system flushbuffer_cache;
System altered.
2、 查看该表的物理信息,比如放在哪个文件上、哪个块上,多少行?
SQL> l
1 select rowid,
2 dbms_rowid.rowid_relative_fno(rowid)file_no,
3 dbms_rowid.rowid_block_number(rowid)block_no,
4 dbms_rowid.rowid_row_number(rowid) row_no,
5 msg,
6 id
7* from lihm.t
SQL>/
ROWID FILE_NO BLOCK_NO ROW_NO MSG ID
---------------------------- ---------- ---------- -----
AAANPWAAEAAAAANAAA 4 13 0 aaa 1
AAANPWAAEAAAAANAAB 4 13 1 bbb 2
AAANPWAAEAAAAANAAC 4 13 2 ccc 3
以第二行为例,我们的目的是把bbb修改成yyy
3、 生成bbed的配置文件
SQL>spool /home/oracle/bbed/filelist.txt
SQL>l
1* selectfile#||' '||name||' '||bytes from v$datafile
SQL>/
1/u02/app/oracle/oradata/ora10g/system01.dbf 524288000
2/u02/app/oracle/oradata/ora10g/undotbs01.dbf 398458880
3/u02/app/oracle/oradata/ora10g/sysaux01.dbf 283115520
4/u02/app/oracle/oradata/ora10g/users01.dbf 10485760
SQL> spooloff
[oracle@hadoop1bbed]$ pwd
/home/oracle/bbed
[oracle@hadoop1bbed]$ cat filelist.txt
1 /u02/app/oracle/oradata/ora10g/system01.dbf 524288000
2/u02/app/oracle/oradata/ora10g/undotbs01.dbf 398458880
3 /u02/app/oracle/oradata/ora10g/sysaux01.dbf 283115520
4 /u02/app/oracle/oradata/ora10g/users01.dbf10485760
[oracle@hadoop1bbed]$ cat bbed.par
blocksize=8192
listfile=/home/oracle/bbed/filelist.txt
mode=edit
在这里我们用到了两个配置文件,一个是filelist.txt另一个是bbed.par这两个文件里的参数也
可以在命令行直接输入,但为方便,我直接写在配置文件里了
4、 进入bbed并找到t表里第二条记录的地址
[oracle@hadoop1 bbed]$bbed parfile=bbed.par
Password:
BBED:Release 2.0.0.0.0 - Limited Production on чǚ?8? 12 10:57:58 2013
Copyright(c) 1982, 2007, Oracle. All rightsreserved.
*************!!! For Oracle Internal Use only !!! ***************
BBED> info
File# Name Size(blks)
----- ---- ----------
1 /u02/app/oracle/oradata/ora10g/system01.dbf 64000
2 /u02/app/oracle/oradata/ora10g/undotbs01.dbf 48640
3 /u02/app/oracle/oradata/ora10g/sysaux01.dbf 34560
4 /u02/app/oracle/oradata/ora10g/users01.dbf 1280
BBED>set file 4 block 13##文件号和块号是我们在第二步中查出来的,直接指定
FILE# 4
BLOCK# 13
BBED> map
File:/u02/app/oracle/oradata/ora10g/users01.dbf (4)
Block: 13 Dba:0x0100000d
------------------------------------------------------------
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes @0
struct ktbbh, 72 bytes @20
struct kdbh, 14 bytes @100
struct kdbt[1], 4 bytes @114
sb2 kdbr[3] @118 ##可以看到有三条记录
ub1 freespace[8034] @124
ub1 rowdata[30] @8158
ub4 tailchk @8188
kdbr是一个长度为三的数组,数组指针占用2字节的长度,里面每一个元素存放的是对应记录的地址,
并且可以使用星号解引用来查看内部数据,也就是说kdbr是一个二级指针,呵呵,还算挺有趣的吧,如果学过C语言的话,对这个比较好理解。
BBED>p kdbr
sb2 kdbr[0] @118 8078
sb2 kdbr[1] @120 8068
sb2 kdbr[2] @122 8058
以第一行为例:kdbr[0]下标式数组访问,@118第一个元素在块内的偏移量,8078代表该元素的值,也就是说,8078代表第一行数据在块内的偏移量,从这三条数据也可以看出,数据存放的格式:
118<120<122 记录的指针从上向下存储
8078>8068>8058 记录里的数据从下向上存储
中间的称为free区,当指针和数据相遇后,那块就满了,当然这只是理论推测。
因为我们要修改第二条记录,那先看下这条记录的数据
BBED>p *kdbr[1]
rowdata[10]
-----------
ub1 rowdata[10] @8168 0x2c
BBED>x /rcn
rowdata[10] @8168
-----------
flag@8168: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8169: 0x01
cols@8170: 2
col 0[3] @8171: bbb
col 1[2] @8175: 2
可以看到正好是我们想要修改的数据,那就直接修改吧,首先确定修改的偏移量
BBED>d /v offset 8171
File:/u02/app/oracle/oradata/ora10g/users01.dbf (4)
Block:13 Offsets: 8171 to 8191 Dba:0x0100000d
-------------------------------------------------------
03626262 02c1032c 01020361 616102c1 l.bbb...,...aaa..
020106bf 7e l ....~s
<16bytes per line>
bbb所在的位置为8172,因为8171存放的是字段长度1字节
不放心的话可以用find的命令查找下
BBED>find /c bbb top
File:/u02/app/oracle/oradata/ora10g/users01.dbf (4)
Block:13 Offsets:8172 to 8191 Dba:0x0100000d
------------------------------------------------------------------------
62626202 c1032c01 02036161 6102c102 0106bf7e
<32bytes per line>
现在可以确定了,就从8172修改
BBED>modify /c yyy offset 8172 ##该命令用来修改数据
Warning: contents of previous BIFILE will belost. Proceed? (Y/N) Y
File:/u02/app/oracle/oradata/ora10g/users01.dbf (4)
Block:13 Offsets: 8172 to8191 Dba:0x0100000d
------------------------------------------------------------------------
79797902 c1032c01 02036161 6102c102 0106bf7e
<32bytes per line>
BBED>p *kdbr[1]
rowdata[10]
-----------
ub1 rowdata[10] @8168 0x2c
BBED>x /rcn
rowdata[10] @8168
-----------
flag@8168: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8169: 0x01
cols@8170: 2
col 0[3] @8171: yyy
col 1[2] @8175: 2
可以看到已经修改过来了,然后应用校验码
BBED> sum
Check valuefor File 4, Block 13:
current =0xde75, required = 0xc575
BBED> sum apply
Check valuefor File 4, Block 13:
current =0xc575, required = 0xc575
5、 验证修改
SQL> select * from t;
MSG ID
--------------------------------------------------
aaa 1
yyy 2
ccc 3
可以看到已经修改过来了。