ORA-01578: ORACLE 數據塊損壞 (文件號 10, 塊號 57896)ORA-01110: 數據文件 10: '/data/oradata/prod35.dbf'


https://community.oracle.com/thread/3540795

概述

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

數據庫壞塊(corruption) 的類型可以按照壞塊所屬對象的不同,分為用戶數據壞塊,數據字典壞塊,Undo壞塊,控制文件壞塊,Redo壞塊,Lob壞塊,index壞塊等等;也可以按照壞塊產生的原因,分為物理壞塊(physical corruption)和邏輯壞塊(logical corruption )。

 

本文主要討論用戶數據發生物理壞塊(physical corruption)分析和解決方法。

 

物理壞塊

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

常見的物理壞塊(Physical Block Corruptions)有塊頭和塊尾信息不一致(Fractured/Incomplete),checksum值無效,數據塊信息全部為0等情況,並且可能伴隨錯誤ORA-1578和ORA-1110

 

為了及時發現物理壞塊和准確定位壞塊產生的原因,oracle建議設置初始化參數DB_BLOCK_CHECKSUM=TYPICAL(默認值)。一般情況下,物理壞塊是由於底層OS/disk系統錯誤/損壞,導致數據塊被修改,數據塊標志為壞塊(corruption)。

 

Case分享

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

數據塊的Checksum值無效是一種常見的物理壞塊,當數據庫初始化參數DB_BLOCK_CHECKSUM=TYPICAL(默認值)時,DBWR進程將數據塊寫入disk時會計算數據塊的Checksum,並且將Checksum值記錄在數據塊的位置offset 16和17;當從disk讀取該數據塊時,oracle重新計算數據塊的Checksum,並且與記錄在數據塊中的Checksum做異或運算(Xor),如果異或結果為非0,說明數據塊被修改過,數據塊為壞塊(corruption)。

 

1. 當前數據庫初始化參數配置DB_BLOCK_CHECKSUM=TYPICAL,因此從disk讀取數據塊時校驗checksum:

 

SQL> show parameter DB_BLOCK_CHECKSUM

 

NAME                                 TYPE        VALUE

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

db_block_checksum                    string      TYPICAL

 

2. 查詢表dept時發現有壞塊,報錯信息ORA-1578和ORA-1110,壞塊為file # 4, block # 133

 

SQL> select * from dept;

select * from dept

*

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 4, block # 133)

ORA-01110: data file 4: '/u01/app/oracle/oradata/orcl/users01.dbf'

 

3. 出現以上錯誤的同時在alert log中也有詳細錯誤信息,這些錯誤信息說明數據塊(file # 4, block # 133)損壞的原因是checksum無效。數據塊中記錄的checksum值為0x8167(這個值是上一次DBWR寫入磁盤時計算的),讀取數據塊時重新計算得到的checksum是0x8122,checksum值異或運算(Xor)的結果是0x45 (computed block checksum)。由於兩次checksum值不同(即異或結果為非0),說明數據塊被修改過,數據塊為壞塊(corruption)。

 

Alert log錯誤信息:

 

Hex dump of (file 4, block 133) in trace file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_20892.trc

Corrupt block relative dba: 0x01000085 (file 4, block 133)

Bad check value found during multiblock buffer read  <<<<<<<<<<<<<< 說明壞塊的原因是checksum無效

Data in bad block:

type: 6 format: 2 rdba: 0x01000085

last change scn: 0x0000.0023d69a seq: 0x5 flg: 0x06

spare1: 0x0 spare2: 0x0 spare3: 0x0

consistency value in tail: 0xd69a0605

check value in block header: 0x8167   <<<<<<<<<<<<<< 數據塊中記錄的checksum值為0x8167

computed block checksum: 0x45         <<<<<<<<<<<<<< 0x8167與0x8122異或運算(Xor)的結果是0x45

Reading datafile '/u01/app/oracle/oradata/orcl/users01.dbf' for corruption at rdba: 0x01000085 (file 4, block 133)

Reread (file 4, block 133) found same corrupt data (no logical check)

Sun Mar 23 22:53:40 2014

Corrupt Block Found

 

         TSN = 4, TSNAME = USERS

         RFN = 4, BLK = 133, RDBA = 16777349

         OBJN = 14343, OBJD = 14343, OBJECT = DEPT, SUBOBJECT =

         SEGMENT OWNER = JAMES, SEGMENT TYPE = Table Segment         <<<<<<<<<<<<<< 壞塊對應的object ID

Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_20892.trc  (incident=182595):

ORA-01578: ORACLE data block corrupted (file # 4, block # 133)

ORA-01110: data file 4: '/u01/app/oracle/oradata/orcl/users01.dbf'

 

4.1 對應的orcl_ora_20892.trc中也有數據塊的信息,其中數據塊上記錄的checksum值是0x8167(chkval)

Block dump from disk:

buffer tsn: 4 rdba: 0x01000085 (4/133)

scn: 0x0000.0023d69a seq: 0x05 flg: 0x06 tail: 0xd69a0605

frmt: 0x02 chkval: 0x8167 type: 0x06=trans data

Hex dump of block: st=0, typ_found=1

 

4.2 通過dd也查看數據塊中記錄的checksum值, offset 16,17 對應的是checksum值0x8167

$ dd if=/u01/app/oracle/oradata/orcl/users01.dbf bs=8192 count=1 skip=133 of=/tmp/dd133.out

 

$ od -x /tmp/dd133.out

0000000 a206 0000 0085 0100 d69a 0023 0000 0605

0000020 8167 0000 0001 0000 3807 0000 2fef 000c

        ^^^^

 

5. 修復數據壞塊的方法可以通過備份恢復或者DBMS_REPAIR.SKIP_CORRUPT_BLOCKS跳過壞塊。

 

5.1 方法#1 RMAN數據塊恢復:

RMAN> run {blockrecover datafile 4 block 133;}

SQL> select * from dept;

 

    DEPTNO DNAME          LOC

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

        10 ACCOUNTING     DALIAN

        20 RESEARCH       DALLAS

        30 SALES          CHICAGO

        40 OPERATIONS     BOSTON

 

5.2 方法#2 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS跳過壞塊,然后將dept表中的其他數據導出重建表

 

SQL> alter session set db_file_multiblock_read_count=1;

SQL> execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('JAMES','DEPT');

SQL> create table dept_new as select * from dept;

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM