BBED我相信大家都已经很熟悉它的用法了,在充分了解block结构的基础上善用BBED确实可以解决很多block内的逻辑错误,但遗憾的是windows平台上的9iR2和 10gR2并不带BBED。
如果我们想在windows平台上用BBED修改数据该怎么办?
其实这里是可以采取变通的办法的,那就是用DD和ultraEdit来替代BBED。好了,我们来看一个实际的例子。
SQL> conn scott/tiger@cuihua;
Connected to Oracle Database
Connected as scott
SQL> select file_name,file_id,bytes from dba_data_files where tablespace_name='USERS';
FILE_NAME FILE_ID BYTES
-------------------------------------------------------------------------------- ---------- ----------
D:\ORACLE\ORADATA\CUIHUA\USERS01.DBF 4 61603840
SQL> create table t2(c1 number,c2 varchar2(5));
Table created
SQL> insert into t2 values(1,'a');
1 row inserted
SQL> insert into t2 values(2,'b');
1 row inserted
SQL> insert into t2 values(3,'c');
1 row inserted
SQL> commit;
Commit complete
SQL> alter system checkpoint;
System altered
SQL> select c1,c2,dbms_rowid.rowid_relative_fno(rowid)||'_'||dbms_rowid.rowid_block_number(rowid) location from t2;
C
---------- ----- --------------------------------------------------------------------------------
2 b 4_1648
现在我们来用DD把上述第二条记录的C2的值由b改成d。
shutdown上述数据库,把"D:\ORACLE\ORADATA\CUIHUA\USERS01.DBF"ftp到AIX上去,然后用dd把 1648这个block拷出来:
$ dd if=/iprat01/USERS01.DBF of=/iprat01/users01.dd count=1 skip=1648 bs=8192
1+0 records in.
1+0 records out.
接着把users01.dd ftp到windows上后用ultraEdit来改,ultraEdit里可以很方便的看到offset:
00001fe0h: 00 00 00 00
00001ff0h: C1 03 01 62
我们现在是想把t2中第二条记录的C2字段的值由b改成d,d所对应的存储格式为:
SQL> select dump('d',16) from dual;
DUMP('D',16)
----------------
Typ=96 Len=1: 64
所以这里我们只需要把62改成64就可以了。
当然这里改完后要把上述block的16、 17位清零,同时把15位改成0x04。这么做是为了让oracle帮我算出来上述block在更改数据后的checksum值是多少。
BBED里不用这么麻烦,因为sum apply时候BBED已经把正确的checksum值算出来并写回去了。
改完后保存,然后把修改过的users01.dd ftp到AIX上再用dd拷回去:
$ dd if=/iprat01/users01.dd of=/iprat01/USERS01.DBF bs=8192 seek=1648 count=1 conv=notrunc
1+0 records in.
1+0 records out.
拷回去后再把已经被修改过的USERS01.DBF ftp下来,然后覆盖windows上原有同名文件并startup上述数据库:
C:\Documents and Settings\cuihua>sqlplus /nolog
SQL*Plus: Release
Copyright (c) 1982, 2005, Oracle. All rights reserved.
SQL> conn / as sysdba;
已连接到空闲例程。
SQL> startup
ORACLE 例程已经启动。
Total System Global Area 608174080 bytes
Fixed Size 1250404 bytes
Variable Size 209718172 bytes
Database Buffers 390070272 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
数据库已经打开。
SQL> select * from scott.t2;
select * from scott.t2
*
第 1 行出现错误:
ORA-01578: ORACLE 数据块损坏 (文件号 4, 块号 1648)
ORA-01110: 数据文件 4: 'D:\ORACLE\ORADATA\CUIHUA\USERS01.DBF'
这是必然的,因为checksum值已经发生了变化。
看一下alert log:
Corrupt block relative dba: 0x01000670 (file 4, block 1648)
Bad check value found during buffer read
Data in bad block:
type: 6 format: 2 rdba: 0x01000670
last change scn: 0x0000.001590e6 seq: 0x1 flg: 0x04
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x90e60601
check value in block header: 0x0
computed block checksum: 0xd2ca
Reread of rdba: 0x01000670 (file 4, block 1648) found same corrupted data
好了,那这里我们就按照上述alert log的提示再改一次checksum值,注意这里改的时候要将第16位、第17位改成CA D2(因为windows是little endian),改完后再次startup上述数据库:
SQL> startup
ORACLE 例程已经启动。
Total System Global Area 608174080 bytes
Fixed Size 1250404 bytes
Variable Size 230689692 bytes
Database Buffers 369098752 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
数据库已经打开。
SQL> select * from scott.t2;
C
---------- -----
2 d
可以看到,我们已经成功的用DD配合ultraEdit把上述第二条记录的C2的值由b改成了d。
很厉害,有没有你学习过程中的资料分享点,谢谢
我所有的资料均来源于oracle的官方文档、metalink和DSI,这些资料大家应该都有。