整体上来讲,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资源来生成校验值以及进行内存块的验证。
同一时候。该操作easy引起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,此时数据块的标志位已发生改动。