您好,欢迎访问一九零五行业门户网

DBMS_REPAIR包使用详解

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 例程已经启动。
其它类似信息

推荐信息