使用DBMS_REPAIR包修复坏块(二)

使用DBMS_REPAIR包修复坏块(二)
使用DBMS_REPAIR包修复坏块(二)
 
    昨天简单得了解了一下关于数据块损坏后该如何操作,都是一些理论知识,当然理论知识也还没有学完 。今天来继续学习理论知识,并且在完成之后找一个实例来实践一下。好,下面开始。
--------------------------------------
 
 
二、评估使用DBMS_REPAIR的损益
 
    要判断损益,需要了解一下问题:
 
    1、损坏的盘区是什么?
 
    这一步比较简单,执行CHECK_OBJECT过程,然后查询修复表即可。
 
    2、其他可用于处理数据损坏的方法是什么?
 
    需要考虑以下几种方法:
    * 假设可以从另一数据源获得数据,则删除、重建、并填充该对象。
    * 对损坏的表发布CREATE TABLE ... AS SELECT语句,以重建新表
    * 通过从选取(select)语句来排除损坏的行来忽略损坏
    * 执行介质恢复
 
    3、当使用DBMS_REPAIR来使一个对象可用时,会引入什么逻辑矛盾或副作用?并考虑代价
 
    主要可能会有以下问题:
    * 标记损坏的数据块中的行会无法访问。
    * 有可能破坏参照完整性约束,如有则需要停用
    * 如果在表上定义了触发器,要考虑如果删除、重新插入数据是否会触发
    * 空闲列表数据块可能不可访问。
        如果损坏数据块在空闲列表的头部或尾部,则空间管理会重新初始化该空闲列表。
        可能会存在该放入空闲列表但有没有放入的数据块,运行REBUILD_FREELISTS解决这个问题。
    * 索引和表不同步了。需要执行DUMP_ORPHAN_KEYS获得信息,然后用ALTER INDEX ... REBUILD ONLINE同步
 
    4、如果修复中丢失了数据,这些数据还能被检索码?
 
    当数据库被标记为损坏时,仍可以从索引中检索数据。DUMP_ORPHAN_KEYS过程可以有助于检索该信息。当然这种方法检索数据取决于索引和表之间数据冗余的数量。
 
 
 
三、使对象可用
 
    1、损坏修复(使用FIX_CORRUPT_BLOCKS和SKIP_CORRUPT_BLOCKS)
 
    通过建立一个环境,跳过DBMS_REPAIR修复能力范围之外的损坏,使损坏对象可用。如果该损坏包括了数据丢失,如数据块中的坏行,所有这样的数据块都被FIX_CORRUPT_BLOCKS过程标记为损坏。然后运行SKIP_CORRUPT_BLOCKS跳过对象中被标记为损坏的数据块。当设置跳过后,表和索引扫描就跳过所有被标记成损坏的数据块,这适用于介质和软件损坏数据块两者。
 
    2、跳过损坏数据块时的意义
 
    如果索引和表不同步了,那么当一个查询仅仅探查索引,而下一个查询探查索引和表两者时,SET TRANSACTION READ ONLY事务就可能有矛盾。如果表数据块被标记成损坏,那么两个查询就会返回不同的结果,这就破坏了只读事务的规则。
    处理这个问题的一个方法是在SET TRANSACTION READ ONLY事务中不跳过损坏数据块。当选取被链接在一起的行时也会发生相同的问题,本质上说,对相同行的查询既可以又不可以访问损坏数据块,因此产生不同结果
 
 
 
四、修复损坏和重建丢失的数据
 
    1、用DUMP_ORPHAN_KEYS过程恢复数据
 
    DUMP_ORPHAN_KEYS过程报告指向损坏数据块中的行的索引项。所有这些索引项都被插入到一个孤立键表中,该表存储了损坏数据块的键和行标识。索引出了索引项信息之后,就可以使用ALTER INDEX ... REBUILD ONLINE语句重建该索引。
 
    2、用REBUILD_FREELISTS过程修复空闲列表
 
    如果是空闲列表(SEGMENT SPACE MANAGEMENT MANUAL)来管理段中的空闲空间时,就使用该过程。
 
    当在空闲列表的头部或尾部找到了被标记为“损坏”的数据块时,将重新初始化空闲列表,并返回一个错误。这样虽然从空闲列表中清除了错误数据块,但是它使得空闲列表不能访问紧跟损坏数据块之后的所有数据块,此时可以使用REBUILD_FREELISTS过程来重新初始化空闲列表。 此时对象会被扫描,若适合作为空闲列表上的数据块,则增加到这里面。
 
    3、用SEGMENT_FIX_STATUS过程修复段位图
 
    对于用位图(SEGMENT SPACE MANAGEMENT AUTO)来管理段中的空闲空间时,使用这个过程。这个过程或者基于对应的数据块的当前内容重新计算位图的状态,或者指定将位图项设置成特殊的值。通常,状态被正确得中心计算而不需要强行设置。
 
 
 
五、示例
 
---------------------------------------------
-- 首先用ADMIN_TABLES建立修复表/孤立键表
-- 修复表用于表示错误数据块以及修复方法
-- 修复表 -> FIX_CORRUPT_BLOCKS
-- 孤立键表 -> DUMP_ORPHAN_KEYS
---------------------------------------------
 
--先来建立修复表
begin
  dbms_repair.admin_tables(table_name => 'REPAIR_WXQ',
                           table_type => dbms_repair.repair_table,
                           action     => dbms_repair.create_action,
                           tablespace => 'WXQ_TBS2');
end;
/
 
--查看一下
SQL> desc REPAIR_WXQ
Name                Type           Nullable Default Comments
------------------- -------------- -------- ------- --------
OBJECT_ID           NUMBER                                  
TABLESPACE_ID       NUMBER                                  
RELATIVE_FILE_ID    NUMBER                                  
BLOCK_ID            NUMBER                                  
CORRUPT_TYPE        NUMBER                                  
SCHEMA_NAME         VARCHAR2(30)                            
OBJECT_NAME         VARCHAR2(30)                            
BASEOBJECT_NAME     VARCHAR2(30)   Y                        
PARTITION_NAME      VARCHAR2(30)   Y                        
CORRUPT_DESCRIPTION VARCHAR2(2000) Y                        
REPAIR_DESCRIPTION  VARCHAR2(200)  Y                        
MARKED_CORRUPT      VARCHAR2(10)                            
CHECK_TIMESTAMP     DATE                                    
FIX_TIMESTAMP       DATE           Y                        
REFORMAT_TIMESTAMP  DATE           Y                        
 
-- 用同样的过程创建孤立键表
begin
  dbms_repair.admin_tables(table_name => 'ORPHAN_WXQ',
                           table_type => dbms_repair.orphan_table,
                           action     => dbms_repair.create_action,
                           tablespace => 'WXQ_TBS2');
end;
/
 
--同样来查看一下表结构
SQL> desc ORPHAN_WXQ
Name           Type         Nullable Default Comments
-------------- ------------ -------- ------- --------
SCHEMA_NAME    VARCHAR2(30)                          
INDEX_NAME     VARCHAR2(30)                          
IPART_NAME     VARCHAR2(30) Y                        
INDEX_ID       NUMBER                                
TABLE_NAME     VARCHAR2(30)                          
PART_NAME      VARCHAR2(30) Y                        
TABLE_ID       NUMBER                                
KEYROWID       UROWID(4000)                          
KEY            UROWID(4000)                          
DUMP_TIMESTAMP DATE                                  
 
 
 

---------------------------------------------
-- 接着用CHECK_OBJECT来检查损坏数量
-- 注意:最终输出为一个int型数字
---------------------------------------------
declare
  num_corrupt int := 0;
begin
  dbms_repair.check_object(schema_name       => 'WANGXIAOQI',
                           object_name       => 'T1',
                           repair_table_name => 'REPAIR_WXQ',
                           corrupt_count     => num_corrupt);
  dbms_output.put_line('number corrupt: ' || to_char(num_corrupt));
end;
/
 
-- 查看修复表
select a.object_name,
       a.block_id,
       a.corrupt_type,
       a.marked_corrupt,
       a.corrupt_description,
       a.repair_description
  from repair_wxq a;
 
OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIPTION REPAIR_DESCRIPTION
----------- -------- ------------ ---------- ------------------- ------------------
         T1        3            1      FALSE                ....               ....
 

---------------------------------------------
-- 使用FIX_CORRUPT_BLOCKS来修理损坏数据块
--
---------------------------------------------
declare
  num_fix int := 0;
begin
  dbms_repair.fix_corrupt_blocks(schema_name       => 'WANGXIAOQI',
                                 object_name       => 'T1',
                                 object_type       => dbms_repair.table_object,
                                 repair_table_name => 'REPAIR_WXQ',
                                 fix_count     => num_fix);
  dbms_output.put_line('num fix: ' || to_char(num_fix));
end;
/
 
--确认已做修复
select a.object_name, a.block_id, a.marked_corrupt
  from repair_wxq a;
 
OBJECT_NAME BLOCK_ID MARKED_COR
----------- -------- ----------
         T1        3      FALSE
 

----------------------------------------------------
-- 使用DUMP_ORPHAN_KEYS来查找指向损坏数据块的指引项
--
----------------------------------------------------
declare
  num_orphans int := 0;
begin
  dbms_repair.dump_orphan_keys(schema_name       => 'WANGXIAOQI',
                               object_name       => 'T1_PK',
                               object_type       => dbms_repair.index_object,
                               repair_table_name => 'REPAIR_WXQ',
                               orphan_table_name => 'ORPHAN_WXQ',
                               key_count         => num_orphans);
  dbms_output.put_line('orphan key count: ' || to_char(num_orphans));
end;
/
 

---------------------------------------------
-- 使用REBUILD_FREELISTS重建空闲列表
--
---------------------------------------------
begin
  dbms_repair.rebuild_freelists(schema_name => 'WANGXIAOQI',
                                object_name => 'T1',
                                object_type => dbms_repair.table_object);
end;
/
 

---------------------------------------------
-- 使用SKIP_CORRUPT_BLOCKS控制是否跳过坏块
--
---------------------------------------------
begin
  dbms_repair.skip_corrupt_blocks(schema_name => 'WANGXIAOQI',
                                  object_name => 'T1',
                                  object_type => dbms_repair.table_object,
                                  flags       => dbms_repair.SKIP_FLAG);
end;
/
 
--查看该表状态
select owner, table_name, skip_corrupt
  from dba_tables
where table_name = 'T1';
 
 
 
 
 

你可能感兴趣的:(使用DBMS_REPAIR包修复坏块(二))