首页 > 数据库 > Oracle > DBMS_REPAIR
今日学习了杨版主的数据恢复的关于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/ ,如需转载,请注明出处,否则将追究法律责任。