当前位置导航:炫浪网>>网络学院>>编程开发>>Oracle教程

DBMS_REPAIR包修复损坏数据块

1 、DBMS_REPAIR包的使用

Oracle提供的DBMS_REPAIR包可以发现、标识并修改数据文件中的坏块。

DBMS_REPAIR包的工作原理比较简单——将检查到的坏块标注出来,使随后的dml操作跳过该块。同时,DBMS_REPAIR包还提供了几个过程,可以用来保存索引的键值(这些键值指向被标注为坏块的block)的过程,以及修复freelists和segment bitmap的过程。

DBMS_REPAIR包不但可以检测出坏块,根据表被索引的情况,还可以用来在一定程度上恢复坏块中的数据。

需要注意,DBMS_REPAIR包没有进行授权,默认情况下,只有sys用户可以执行。

下面通过一个完整的例子来说明DBMS_REPAIR包的使用。

第一步:构造测试环境

首先建立一个测试用表空间,由于需要用UltraEdit打开数据文件修改部分内容来模拟错误,因此数据文件要建的小一些。

SQL> CREATE TABLESPACE TEST DATAFILE 'E:\ORACLE\ORADATA\TEST\TEST.DBF' SIZE 1M

2 EXTENT MANAGEMENT LOCAL AUTOALLOCATE SEGMENT SPACE MANAGEMENT MANUAL;

表空间已创建。

SQL> CREATE TABLE TEST (ID NUMBER, NAME VARCHAR2(30)) TABLESPACE TEST;

表已创建。

SQL> INSERT INTO TEST SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS;

已创建6232行。

SQL> COMMIT;

提交完成。

SQL> CREATE INDEX IND_TEST_ID ON TEST (ID);

索引已创建。

SQL> CREATE INDEX IND_TEST_NAME ON TEST (NAME);

索引已创建。

为了确保数据库已经把刚才插入的数据写到数据文件中,现在重起数据库。

SQL> CONN /@TEST AS SYSDBA

已连接。

SQL> SHUTDOWN

数据库已经关闭。

已经卸载数据库。

ORACLE 例程已经关闭。

SQL> STARTUP

ORACLE 例程已经启动。

Total System Global Area 89201304 bytes

Fixed Size 453272 bytes

Variable Size 62914560 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。

数据库已经打开。

第二步:模拟错误的产生

用UltraEdit打开数据文件,只要修改了数据文件中任意的一个位置,都会造成数据文件错误。但我们测试需要将错误发生位置定位在TEST表中。

SQL> CONN YANGTK/YANGTK@TEST

已连接。

SQL> SELECT SUBSTR(ROWID, 10, 6), ID, NAME FROM TEST WHERE ID = 123;

SUBSTR(ROWID ID NAME

------------ ---------- ------------------------------

AAAAAG 123 ALL_REPCONFLICT

如何在数据文件中找到TEST表的数据呢?可以通过ROWID来定位的记录在数据文件中的位置。任意选择一条记录(如上面ID = 123),取得它的ROWID,我们知道,ROWID中10~15位表示这条记录所在的BLOCK是数据文件的第几个BLOCK。

A表示0,B为1,G表示6。这说明这条记录在数据文件的第六个block中。

SQL> SHOW PARAMETER DB_BLOCK_SIZE

NAME TYPE VALUE

------------------------------------ ----------- ---------------

db_block_size integer 16384

BLOCK的大小是16k。

SQL> SELECT TO_CHAR(6*16384, 'XXXXXX') FROM DUAL;

TO_CHAR

-------

18000

SQL> SELECT TO_CHAR(7*16384, 'XXXXXX') FROM DUAL;

TO_CHAR

-------

1C000

用UltraEdit打开数据文件,将文件定位18000h处(以二进制方式打开,如果没有用二进制打开,可以使用CTRL+H快捷键切换)。根据上面的计算,可以得出,我们要找到记录在18000h和1C000h之间。

Number类型123在数据库存放方式为03C20218,03表示占有三位,C2表示最高位是百位,02表示最高位上是1,18表示低位上是23。(如果对Oracle的基本数据类型的存储格式感兴趣,可以参考我在论坛上的帖子)

具体的数值可以通过下面的查询得到:

SQL> SELECT DUMP(123, 16) FROM DUAL;

DUMP(123,16)

--------------------

Typ=2 Len=3: c2,2,18

下面使用UltraEdit的搜索功能,查找到03C20218,将其修改为03C20216,并保存。

上面是通过Oracle的ROWID在文件中定位,这相对来说要复杂一些。下面可以直接使用UltraEdit的搜索功能达到相同的目的。

根据上面的查询可以得到,ID = 123时,NAME的值是ALL_REPCONFLICT。

下面用UltraEdit打开文件,使用CTRL+H方式切换到文本格式,直接查找ALL_REPCONFLICT字符串。找到后,CTRL+H切换回二进制格式。向前跳过一个长度字节(本例中为0F),就可以看到123的值03C20218,进行修改后,保存并退出。

SQL> SELECT * FROM TEST WHERE ID = 123;

ID NAME

---------- ------------------------------

123 ALL_REPCONFLICT

这时候查询仍然可以得到正确结果,因为oracle使用了db_cache中的结果。为了让oracle“看”到修改,必须重起数据库。

SQL> CONN /@TEST AS SYSDBA

已连接。

SQL> SHUTDOWN

数据库已经关闭。

已经卸载数据库。

ORACLE 例程已经关闭。

SQL> STARTUP

ORACLE 例程已经启动。

Total System Global Area 89201304 bytes

Fixed Size 453272 bytes

Variable Size 62914560 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。
        
        数据库已经打开。

SQL> CONN YANGTK/YANGTK@TEST

已连接。

SQL> SELECT * FROM TEST WHERE ID = 123;

SELECT * FROM TEST WHERE ID = 123

*

ERROR 位于第 1 行:

ORA-01578: ORACLE 数据块损坏(文件号7,块号6)

ORA-01110: 数据文件 7: 'E:\ORACLE\ORADATA\TEST\TEST.DBF'

已经模拟成功了坏块,开始进入正题部分,使用DBMS_REPAIR表来处理坏块。

 

[1] [2] [3] [4] 下一页  

相关内容
赞助商链接