ITPub博客

首页 > 数据库 > Oracle > DBMS_REPAIR

DBMS_REPAIR

Oracle 作者:abstractcyj 时间:2014-08-19 09:05:41 0 删除 编辑

今日学习了杨版主的数据恢复的关于DBMS_REPAIR的内容。



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

构建测试环境。表空间数据文件只有1M,因为要修改数据文件模拟数据库信息。
create tablespace mytest datafile 'E:\data\oradata\test.dbf' size 1m extent management local autoallocate segment space management manual;

alter user scott quota unlimited on mytest;

alter user scott account unlock identified by tiger;

insert into test select object_id, object_name from sys.dba_objects
where rownum <= 10000;

通过UltraEdit修改了数据文件,使得查询报错。
修改之后,必须重启数据库,因为oracle使用buffer cache来满足查询



接下来开始修复的过程:
1. 建立REPAIR_TABLE与ORPHAN_KEY_TABLE, REPAIR_TABLE用来记录错误检查结果,ORPHAN_KEY_TABLE用来记录表坏块中记录在索引对应键值。
BEGIN
  sys.dbms_repair.admin_tables(table_name => 'REPAIR_TABLE',
                               table_type => sys.dbms_repair.repair_table,
                               action     => sys.dbms_repair.create_action,
                               tablespace => 'USERS');
END;

BEGIN
  sys.dbms_repair.admin_tables(table_name => 'ORPHAN_KEY_TABLE',
                               table_type => sys.dbms_repair.ORPHAN_TABLE,
                               action     => sys.dbms_repair.create_action,
                               tablespace => 'USERS');
END;
2. 使用CHECK_OBJECT过程检测坏块

DECLARE
  v_num_corrupt NUMBER := 0;
BEGIN
  sys.dbms_repair.check_object(schema_name       => 'SCOTT',
                               object_name       => 'TEST',
                               repair_table_name => 'REPAIR_TABLE',
                               corrupt_count     => v_num_corrupt);
  dbms_output.put_line('corrupted block:' || v_num_corrupt);
END;



3. 使用DUMP_ORPHAN_KEYS过程来保存坏块中的键值。问题:表出现了坏块,但是索引没有损坏,通过表扫描仍然出现错误,但是通过索引扫描仍然可以返回结果,
这会造成数据的不一致性。通过DUMP_ORPHAN_KEYS过程来保存坏块中的索引键值,这样当执行完SKIP_CORRUPT_BLOCKS操作后就能重新建立索引了。
DECLARE
  v_orphan_num NUMBER;
BEGIN
  sys.dbms_repair.dump_orphan_keys(schema_name       =>'SCOTT',
                                   object_name       => 'INDX_TEST1',
                                   repair_table_name =>'REPAIR_TABLE',
                                   orphan_table_name =>'ORPHAN_KEY_TABLE',
                                   key_count         =>v_orphan_num);
                                   
  dbms_output.put_line(v_orphan_num);
END;




DECLARE
  v_orphan_num NUMBER;
BEGIN
  sys.dbms_repair.dump_orphan_keys(schema_name       =>'SCOTT',
                                   object_name       => 'INDX_TEST2',
                                   repair_table_name =>'REPAIR_TABLE',
                                   orphan_table_name =>'ORPHAN_KEY_TABLE',
                                   key_count         =>v_orphan_num);
                                   
  dbms_output.put_line(v_orphan_num);
END;

注意对每个索引都要执行DUMP_ORPHAN_KEYS过程
4. 使用REBUILD_FREELISTS过程来修改FREELISTS
如果坏块发生在FREELISTS列表中的中部,则FREELISTS列表后面的块都无法访问,在这个测试中,错误是人为产生的,清楚知道错误并不在FREELISTS中,因此可以跳过此步骤,一般情况下,无法定位坏块位置,则需要执行该过程。
BEGIN
  sys.dbms_repair.rebuild_freelists(schema_name => 'SCOTT',
                                    object_name => 'TEST',
                                    object_type => sys.dbms_repair.table_object);
END;

5. 执行SKIP_CORRUPT_BLOCKS过程,使后续DML操作跳过坏块
BEGIN
  sys.dbms_repair.skip_corrupt_blocks(schema_name => 'SCOTT',
                                      object_name => 'TEST',
                                      object_type => sys.dbms_repair.table_object);
END;


经过这个步骤之后,表已经可以访问。但是ID=123的那条记录已丢失。

6. 经过步骤5之后,数据与索引仍然存在不一致的问题,因此必须重建索引。
需要注意的是,重建索引一定要先DROP,然后再CREATE,使用REBUILD的方式,重建的数据源来自索引。仍然会导致问题的产生

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8520577/viewspace-1253602/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: RMAN-06059(转)
请登录后发表评论 登录
全部评论
曾从事java方向开发多年。近年已经转入数据库方向。主要擅长SQL优化,Oracle数据库问题诊断,Oracle备份与恢复等。服务于医药物流,医院等行业

注册时间:2010-01-26

  • 博文量
    602
  • 访问量
    1091618