Home >Database >Mysql Tutorial >DBMS_REPAIR包使用详解

DBMS_REPAIR包使用详解

WBOY
WBOYOriginal
2016-06-07 16:45:511356browse

Oracle提供了DBMS_REPAIR包用来发现、标识并修改数据文件中的坏块。任何工具都不是万能的,使用这个包的同时会带来数据丢失、表和

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

任何工具都不是万能的,使用这个包的同时会带来数据丢失、表和索引返回数据不一致,完整性约束破坏等其他问题。因此当出现错误时,应当首先从物理备份或逻辑备份恢复,使用dbms_repair只是在没有备份的情况下使用的一种手段,这种方式一般都会造成数据的丢失。


dbms_repair包的工作原理比较简单,是将检查到的坏块标注出来,使随后的dml操作跳过该块,同时,dbms_repair包还提供了用于保存索引中包含的标注为坏块中的键值,以及修复freelist和segment bitmap的过程。

有一点需要注意,dbms_repair包没有进行授权,只有sys用户可以执行。

下面通过一个例子来简要介绍一下dbms_repair包的使用。

Oracle 11g 在RedHat Linux 5.8_x64平台的安装手册

Linux-6-64下安装Oracle 12C笔记

在CentOS 6.4下安装Oracle 11gR2(x64)

Oracle 11gR2 在VMWare虚拟机中安装步骤

Debian 下 安装 Oracle 11g XE R2

一、构造测试环境

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

SQL> CREATE TABLESPACE TEST DATAFILE 'E:ORACLEORADATATESTTEST.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);


索引已创建。


为了确保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
数据库装载完毕。
数据库已经打开。


 


二、模拟错误的产生

用UtralEdit打开数据文件,只要修改了数据文件中任意的一个位置,都会造成数据文件错误。但我们测试需要将错误发生位置定位在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


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


Number类型123在数据库存放方式为03C20218,,03表示占有三位,C2表示最高位是百位,02表示最高位上是1,18表示低位上是23。


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


SQL> SELECT DUMP(123) FROM DUAL;


DUMP(123)
---------------------
Typ=2 Len=3: 194,2,24


SQL> SELECT TO_CHAR(194, 'XX'), TO_CHAR(2, 'XX'), TO_CHAR(24, 'XX') FROM DUAL;


TO_ TO_ TO_
--- --- ---
 C2  2  18


关于具体的NUMBER类型在数据库中是如何存储的,有兴趣的可以参阅另一篇文章。


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


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


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


下面用UtralEdit打开文件,使用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 例程已经启动。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn