ORACLE 坏块处理

/*==============================================================
#内容概要:
#  坏快的分类,坏块形成的原因,如何检测坏快,修复坏块,参考文档。
#
#version 1.0
#date:20120124
================================================================*/
 
/*---------------------------------------------------------------
#
#坏块形成的原因
#
-----------------------------------------------------------------*/

  1)硬件问题
 
     Oracle进程在处理一个数据块时,首先将其读入物理内存空间,在处理完成后,再由特定进程将其写回磁盘;
    如果在这个过程中,出现内存故障,CPU计算失误,都会导致内存数据块的内容混乱,最后反映到写回磁盘的数据块内容有误。
    同样,如果存储子系统出现异常,数据块损坏也就随之出现了。
  
  2)操作系统BUG
 
     由于Oracle进程对数据块的读写,都是以操作系统内核调用(system call)的方式完成的,如果操作系统在内核调用存在问题,
     必然导致Oracle进程写入非法的内容。
  
  3)操作系统的I/O错误或缓冲问题
  
  4)内存或paging问题
  
  5)Oracle软件BUG
 
     Oracle软件特定版本上,可能出现导致数据块的内容出现异常BUG。
  
  6)非Oracle进程扰乱Oracle共享内存区域
  
     如上文所述,在当数据块的内容被读入主机的物理内存时,如果其他非Oracle进程,对Oracle使用的共享内存区域形成了扰乱,
     最终导致写回磁盘的数据块内容混乱。
  
  7)异常关机,掉电,终止服务
   异常关机,掉电,终止服务使进程异常终止,而破坏数据块的完整性,导致坏块产生。

/*---------------------------------------------------------------
#                                  
#坏块的分类
#
-----------------------------------------------------------------*/
  1)坏块定义:
    在Oracle数据库的一个或多个数据块(一个数据块的容量在创建数据库时由db_block_size参数指定,缺省为8K)内出现内容混乱的现象。
    由于正常的数据块都有固定的合法内容格式,坏块的出现,导致数据库进程无法正常解析数据块的内容,进而使数据库进程报错乃至挂起,
    并级联导致整个数据库实例出现异常。坏块分为物理坏块和逻辑坏块。
  2)物理坏块
     理坏块(也可以称为介质坏块)指的是块格式本身是坏的,块内的数据没有任何意义。
 
    
  3)逻辑坏块 
     逻辑坏块,指的是块内的数据在逻辑是存在问题。
 
    物理坏块和逻辑坏块的分辨方法参见ORACLE DOCUMENT ID 840978.1
   
 
/*---------------------------------------------------------------
#
#检查坏块
#简述发现坏块的方法
#
-----------------------------------------------------------------*/   
1)用户操作发现坏块
   在用户进行DML时返回错误消息(eg ORA-01578,Ora-111).
  
2) 后台alert log 中发现坏块报错(eg ORA-01578: ORACLE数据块损坏(文件号4,块号35)).
3) DBV 检查数据库坏块,针对数据库文件。
   语法如下:
    具体的语法如下:
       关键字     说明                    (默认)      
       ----------------------------------------------------      
       FILE        要验证的文件                 (无)      
       START       起始块                    (文件的第一个块)      
       END         结束块                      (文件的最后一个块)      
       BLOCKSIZE   逻辑块大小             (2048)      
       LOGFILE     输出日志                     (无)      
       FEEDBACK    显示进度               (0)      
       PARFILE     参数文件                 (无)      
       USERID      用户名/口令              (无)      
       SEGMENT_ID  段 ID (tsn.relfile.block) (无)
      
   适用条件及例外:
     
      a. 检查物理坏块和逻辑坏块
      b. 因为dbv要求file后面跟的必须是一个文件扩展名,所以如果用裸设备存储的,就必须使用ln链接裸设备到一个文件,
       然后再用dbv对这个链接文件进行检查.
      
4) 利用exp工具导出整个数据库可以检测坏块
   适用条件及例外:
     
      a. HWM以上的坏块是不会发现的
      b. 索引中存在的坏块是不会发现的
      c. 数据字典中的坏块是不会发现的
      d. 检查物理坏块
5) ANALYZE   
 
   ANALYZE TABLE tablename VALIDATE STRUCTURE CASCADE
   它执行坏块的检查,但是不会标记坏块为corrupt,检测的结果保存在USER_DUMP_DEST目录下的用户trace文件中。
  
   适用条件及例外:
  
      a. 检查逻辑坏块

6) rman
   rman 可以在数据库、表空间、数据文件级检测 数据库坏块,可以指定检测物理或者逻辑坏块,用起来十分方便。
  
   eg.
    BACKUP CHECK LOGICAL VALIDATE DATAFILE n ;(检测逻辑坏块)
    BACKUP   VALIDATE DATAFILE n ;(检测物理坏块 )
 

/*---------------------------------------------------------------
#
#修复坏块
#根据不同的情况处理数据库坏块。
#
-----------------------------------------------------------------*/
  1)通过上面的检测方法检查数据库的坏块,也可以通过查询v$database_currpt_blocks 视图查看数据库现有的坏块情况。
 
  2)用如下SQL检查出现坏快的OBJ.
 
    SELECT tablespace_name, segment_type, owner, segment_name, partition_name  FROM dba_extents WHERE file_id = and between block_id AND block_id + blocks – 1;

     
  3)保存除坏块以外的其他数据
 
    a)利用以上查处的rowid 建备份表保存数据。
     
       A)先取得坏块中ROW ID的最小值,执行以下的语句:            
                                                                         
         SELECT dbms_rowid.rowid_create(1,,,,0) from DUAL; 
                                                                         
       B)取得坏块中的ROW ID的最大值,执行以下的语句:                       
                                                                         
         SELECT dbms_rowid.rowid_create(1,,,+1,0) from DUAL;
        
       C)保存数据
 
        INSERT INTO salvage_table SELECT /*+ ROWID(A) */ * FROM A WHERE rowid < '';
        INSERT INTO salvage_table SELECT /*+ ROWID(A) */ * FROM A  WHERE rowid >= '‘;
       
    b)通过设置 ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10'; 在session 级别跳过坏块,建立备份表。
   
        create table salvage_table as select * from owner.tablename.
       
      通过设置alter session set events='10231 trace name context off' 终止event.     
      10231 trace 也可以在系统级设置,整个系统都会忽略坏块。
     
    c)通过调用 DBMS_REPAIR 包来标记坏块并跳过坏块
     
      A) exec DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE',1,1,'USERS');
         exec DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TABLE',2,1,'USERS');
        
      B)
         Set serveroutput on;
         DECLARE
           cc NUMBER;
         BEGIN
           DBMS_REPAIR.check_object(schema_name=>'SYS',--注意此处是用户名
                                     object_name    =>'DMM',
                                     corrupt_count  =>cc);
           DBMS_OUTPUT.put_line(TO_CHAR(cc));
         END;
      C)
    DECLARE cc  NUMBER;
    BEGIN
      DBMS_REPAIR.fix_corrupt_blocks(schema_name  =>'SYS',
                                      object_name  =>'DMM',
                                      fix_count    =>cc);
      DBMS_OUTPUT.put_line(a=>TO_CHAR(cc));
    END;
      D)execdbms_repair.skip_corrupt_blocks(schema_name=>'SYS',object_name=>'DMM',flags=>1);
        
      create table salvage_table as select * from owner.tablename. 
      
        
  4)修复坏块
             
    a)有恢复整个文件,备份和LOG,数据库在归档模式。
   
      A) 先offline受影响的数据文件,执行以下的语句:
       ALTER DATABASE DATAFILE 'name_file' OFFLINE;
      B) 保留有坏块的数据文件,然后拷贝备份的数据文件。如果恢复的数据文件要求路径不同,执行以下的语句:
         ALTER DATABASE RENAME FILE 'old_name' TO 'new_name';
      C) 恢复数据文件,执行以下语句:
         RECOVER DATAFILE 'name_of_file';
        
      D) Online恢复后的数据文件,执行以下的语句:
         ALTER DATABASE DATAFILE 'name_of_file' ONLINE;
        
    b)只恢复单个块,要求数据库版本是9.2.0以上,要求配置了Rman的catalog数据库,数据库为归档方式,并且有完整的物理备份。
   
        Rman>run{blockrecover datafile 5 block 11,16;}
      
       
    c)没有备份和归档,丢失损坏的数据。如果业务能通过别的途径找出丢失的数据也可以恢复。
   
      A) truncate 该表,再用保存的这个表的其他数据重建这张表。
     
       truncate table owner.table_name
       create tabale owner.table_name as select * from owner.table_name_bak.
      
      B)如果是索引在重建之前需要备份索引的统计信息,重建之后恢复统计信息。
     
        exec dbms_stats.create_stat_table(ownname => 'YYYY',stattab => 'temp_stat_table_20120115');
    exec dbms_stats.export_index_stats(ownname => 'YYYY',indname => 'IND_GM_PREM_NAS_POLNO',stattab => 'temp_stat_table_20120115',statown => 'YYYY');
    
    ALTER INDEX YYYY.IND_GM_PREM_NAS_POLNO REBUILD parallel 12;
    
    exec dbms_stats.import_index_stats(ownname => 'YYYY',indname => 'IND_GM_PREM_NAS_POLNO',stattab => 'temp_stat_table_20120115',statown => 'YYYY',no_invalidate => true,force => true);
 
 

 

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

转载于:http://blog.itpub.net/10113559/viewspace-715223/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值