首页 > 代码库 > oracle block corrupt 坏块

oracle block corrupt 坏块

    总体上来讲,oracle的坏块可以分为两种情景:物理损坏和逻辑损坏。物理损坏是由于存储等原因造成的,致使oracle在处理数据块时发现块的checksum不一致。逻辑损坏多是由于oracle的bug或者内存错误引起,通过检测数据块的checksum并不会发现什么问题,但是在逻辑上这些块已经发生了损坏。

oracle通过两个参数来控制对物理损坏和逻辑损坏的检测:

SQL> show parameter db_block_check

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_block_checking		     string	 FALSE
db_block_checksum		     string	 TRUE

     db_block_checking 是当block发生任何变化的时候进行逻辑上的完整性和正确性检查。该参数能够避免内存中数据块的损坏。块的检查将对系统会有1%到10%的性能影响。取决于对db_block_checking参数的设置。频繁的DML将使得块检查带来更多的开销。在系统负荷允许的情形下建议设置为full。该参数对SYSTEM表空间始终是处于“打开”状态,而不管该参数是否设置为OFF。下面是该参数的设置参考。FALSE和TRUE是为了老版本的兼容。

        Property             Description

        ---------------     ------------

        Parameter type         String

        Syntax                         DB_BLOCK_CHECKING = { FALSE| OFF| LOW | MEDIUM | TRUE| FULL}  -->OFF(=FALSE),FULL(=TRUE)

        Defaultvalue              FALSE

        Modifiable                  ALTER SYSTEM

        Basic                          No

      这里有一点需要注意,即只有在对数据块发生修改时,db_block_checking才会发生作用。如

SQL> show parameter db_block_check

NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_block_checking		     string	 FALSE
db_block_checksum		     string	 TRUE
SQL> alter system flush buffer_cache;

System altered.

SQL> select * from scott.s2;//查询时没有问题

T1	   T2
---------- --------------------
51809	   lllll
51888	   SC
51574	   PK_DEPT
51573	   DEPT
1575EMP,  5
51576	   PK_EMP
51578	   SALGRADE

7 rows selected.

SQL> update scott.s2 set t2='aaaa' where t1='51809';//修改也没有问题

1 row updated.

SQL> commit;

Commit complete.

SQL> alter system flush buffer_cache;

System altered.

SQL> alter system set db_block_checking=true;

System altered.

SQL> select * from scott.s2;//查询是没有问题的

T1	   T2
---------- --------------------
51809	   aaaa
51888	   SC
51574	   PK_DEPT
51573	   DEPT
1575EMP,  5
51576	   PK_EMP
51578	   SALGRADE

7 rows selected.

SQL> update scott.s2 set t2='bbbb' where t1 = '51809';//修改时触发了逻辑检测
update scott.s2 set t2='bbbb' where t1 = '51809'
             *
ERROR at line 1:
ORA-00607: Internal error occurred while making a change to a data block
ORA-00600: internal error code, arguments: [kddummy_blkchk], [5], [20], [6113],
[], [], [], []


SQL> select * from scott.s2;//发现逻辑错误后,oracle将块标记为坏块,此时数据块无法访问了
select * from scott.s2
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 5, block # 20)
ORA-01110: data file 5: '/home/app/oraten/oradata/oraten/tbs201.dbf'


db_block_checksum 用于DBWn和direct loader数据块写入到磁盘时,基于块内的所有字节计算得出一个校验值并将其写入块头。在该参数设置为typical和full时,当读入时候重新计算校验和写出时候的校验对比,如果不同则认为是块损坏。如果设置为FULL模式,则基于update/delete应用程序语句级别的改变发生后,校验值会被重新计算并写入。同时对于日志块,在写入之前,同样会生产校验值并写入到块头。该参数主要是防止IO硬件和IO子系统的错误。如果设置为OFF则只对系统表空间有效。下面是该参数的设置参考。FALSE和TRUE是为了老版本的兼容。

        Property             Description

        ---------------     ------------

        Parameter type         String

        Syntax                         DB_BLOCK_CHECKSUM = { OFF| FALSE| TYPICAL | TRUE| FULL}  -->OFF(=FALSE),FULL(=TRUE)

        Defaultvalue              TYPICAL

       Modifiable                   ALTER SESSION,ALTER SYSTEM

        Basic                          No


对于性能上的差异而言,当设置两个block参数设置为true时,将需要更多的CPU资源来生成校验值以及进行内存块的验证。同时,该操作容易引起redo copy latch的持有时间增加和引起这个latch的竞争。不管db_block_checking和db_block_checksum这两个参数的值为何值,SYSTEM表空间都会进行做checking和checksum,可以通过隐含参数_db_always_check_system_ts设置为FALSE,但为了SYSTEM表空间数据安全,不建议将这个隐含参数值设置为FALSE。


我们已经知道,oracle 将坏块分为物理和逻辑损坏两种,那么当oracle发现物理或者逻辑损坏之后是如何标记数据块从而使之后的操作知道该块是损坏块的那?

对于物理损坏,oracle不会进行任何的处理,在进行后续处理时oracle会重新计算checksum,只要发现checksum不一致则认为该块时物理损坏,并抛出01578错误。

对于逻辑损坏,当oracle第一次对数据块进行逻辑检测时,会抛出ora 600等错误,并修改数据块中的标记位,当下次访问该数据块时,oracle检测标志位,如果发现标志位以置为逻辑损坏,则抛出ora 01578错误。当使用DBMS_REPAIR对坏块进行修改时,如果时物理损坏不作任何处理,如果时逻辑损坏,修改数据块的标志位。


在数据块中存在两个位置表示数据块为逻辑损坏(不标示物理损坏),如下:

BBED> map /v
 File: /home/app/oraten/oradata/oraten/tbs201.dbf (5)
 Block: 20                                    Dba:0x01400014
------------------------------------------------------------
 KTB Data Block (Table/Cluster)

 struct kcbh, 20 bytes                      @0       
    ub1 type_kcbh                           @0       
    ub1 frmt_kcbh                           @1       
    ub1 spare1_kcbh                         @2       
    ub1 spare2_kcbh                         @3       
    ub4 rdba_kcbh                           @4       
    ub4 bas_kcbh                            @8       
    ub2 wrp_kcbh                            @12      
    <strong>ub1 seq_kcbh                            @14  </strong>    
    ub1 flg_kcbh                            @15      
    ub2 chkval_kcbh                         @16      
    ub2 spare3_kcbh                         @18      

 struct ktbbh, 96 bytes                     @20      
    ub1 ktbbhtyp                            @20      
    union ktbbhsid, 4 bytes                 @24      
    struct ktbbhcsc, 8 bytes                @28      
    b2 ktbbhict                             @36      
    ub1 ktbbhflg                            @38      
    ub1 ktbbhfsl                            @39      
    ub4 ktbbhfnx                            @40      
    struct ktbbhitl[3], 72 bytes            @44      

 struct kdbh, 14 bytes                      @124     
    ub1 kdbhflag                            @124     
    b1 kdbhntab                             @125     
    b2 kdbhnrow                             @126     
    sb2 kdbhfrre                            @128     
    sb2 kdbhfsbo                            @130     
    sb2 kdbhfseo                            @132     
    b2 kdbhavsp                             @134     
    b2 kdbhtosp                             @136     

 struct kdbt[1], 4 bytes                    @138     
    b2 kdbtoffs                             @138     
    b2 kdbtnrow                             @140     

 sb2 kdbr[7]                                @142     

 ub1 freespace[7905]                        @156     

 ub1 rowdata[127]                           @8061    

<strong> ub4 tailchk                                @8188</strong>

BBED> set offset 14
	OFFSET         	14

BBED> dump /v count 12
 File: /home/app/oraten/oradata/oraten/tbs201.dbf (5)
 Block: 20      Offsets:   14 to   25  Dba:0x01400014
-------------------------------------------------------
 <strong>ff</strong>0425fe 00000100 0000fcca          l ..%.........

 <16 bytes per line>

BBED> set offset 8188
	OFFSET         	8188

BBED> dump /v count 12
 File: /home/app/oraten/oradata/oraten/tbs201.dbf (5)
 Block: 20      Offsets: 8188 to 8191  Dba:0x01400014
-------------------------------------------------------
 <strong>ff</strong>060000                            l ....
这里的ff即标示数据块位逻辑损坏块,我们可以将其手工修改位01 或者 02 从而取消逻辑损坏标示。


对于已经标示为逻辑损坏的数据块,dbv等工具的检测结果如下:

Total Blocks Examined         : 1
Total Blocks Processed (Data) : 1
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 0
Total Blocks Influx           : 0

而对于没有标示的逻辑损坏,dbv等工具检测结果如下:

Total Blocks Examined         : 1
Total Blocks Processed (Data) : 1
Total Blocks Failing   (Data) : 1
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 0
Total Blocks Influx           : 0


对于物理损坏,dbv检测结果如下
DBVERIFY - Verification complete

Total Blocks Examined         : 1
Total Blocks Processed (Data) : 0
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 1
Total Blocks Influx           : 0


对于dbms_repair包,如果是物理损坏,则REPAIR_TABLE的marked_corrupt列始终为true,fix方法并不会发生作用。对于逻辑损坏,首先repair_table 的marked_corrupt列为false,fix方法修正后,marked_corrupt修改为true,此时数据块的标志位已发生修改。




oracle block corrupt 坏块