總體上來講,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
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