ORA-01578 壞塊原因模擬及解決方法

gaopengtttt發表於2010-08-09

  原創轉載起註明出處
  我們可能有時候會遇到如下錯誤
一、錯誤展示
  SQL> select * from test123;
 
select * from test123
 
ORA-01578: ORACLE data block corrupted (file # 1, block # 61658)
ORA-01110: data file 1: '/oracle_ocfs/oradata/pprac/system01.dbf'
二、原因
    這樣的情況下可能是因為底層的硬體問題引起的,在進行讀物理磁碟資料塊的時候會進行物理一致性校驗,也就是會計算上次寫入磁碟的
時候的校驗和和這次讀取時候的校驗和是否相同,不同則出現錯誤1578,引數db_block_checksum來控制這個功能10G預設是TRUE也就是對
所有檔案進行校驗如果設定為FALSE就是隻對SYSTEM檔案進行校驗。當然還涉及到邏輯檢驗,但是這個錯誤是物理檢驗出錯引起的。
三、校驗工具
    而我們有那些方法進行資料檔案進行壞塊校驗哪?
    1、DBV工具
       命令和結果如下
       [oracle@b000-vmracdb1 lib]$ dbv file=/oracle_ocfs/oradata/pprac/system01.dbf

DBVERIFY: Release 10.2.0.1.0 - Production on Mon Aug 9 16:43:53 2010

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

DBVERIFY - Verification starting : FILE = /oracle_ocfs/oradata/pprac/system01.dbf
Page 61658 is marked corrupt
Corrupt block relative dba: 0x0040f0da (file 1, block 61658)
Bad check value found during dbv:
Data in bad block:
 type: 6 format: 2 rdba: 0x0040f0da
 last change scn: 0x0000.00d056c1 seq: 0x1 flg: 0x06
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0x56c10601
 check value in block header: 0x6988
 computed block checksum: 0xde02


DBVERIFY - Verification complete

Total Pages Examined         : 64000
Total Pages Processed (Data) : 38268
Total Pages Failing   (Data) : 0
Total Pages Processed (Index): 7142
Total Pages Failing   (Index): 0
Total Pages Processed (Other): 1901
Total Pages Processed (Seg)  : 0
Total Pages Failing   (Seg)  : 0
Total Pages Empty            : 16688
Total Pages Marked Corrupt   : 1
Total Pages Influx           : 0
Highest block SCN            : 13691243 (0.13691243)

這裡Total Pages Marked Corrupt   : 1說明有了壞塊  
    2、RMAN工具
      使用命令
       backup check logical validate database;
       同時對物理和邏輯進行校驗
       然後我們可以檢視檢視v$database_block_corruption,結果如下
       SQL> select * from v$database_block_corruption;
 
     FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTION_TYPE
---------- ---------- ---------- ------------------ ---------------
         1      61658          1                  0 CHECKSUM
    3、ANALYZE命令
    命令是:ANALYZE TABLE TEST123 VALIDATE STRUCTURE CASCADE ONLINE;
四、模擬錯誤   
為了試驗我們使用BBED工具進行模擬,千萬不要用這個工具在生產上玩哦。同時要建立一個表如下:
 create table test123
(id number,name char(2000));
然後插入資料我的資料如下:
        ID NAME
---------- --------------------------------------------------------------------------------
         1 test
         2 test2
         3 test3
         4 test4
         5 test5
         6 test6
         7 test7
         8 test8
         9 test9
        10 test10
然後確定檔案號和資料塊好如下:
SQL> select dbms_rowid.rowid_relative_fno(rowid) file_num,
  2   dbms_rowid.rowid_block_number(rowid) block_num,id,name from test123;
 
  FILE_NUM  BLOCK_NUM         ID NAME
---------- ---------- ---------- --------------------------------------------------------------------------------
         1      61658          1 test
         1      61658          2 test2
         1      61658          3 test3
         1      61659          4 test4
         1      61659          5 test5
         1      61659          6 test6
         1      61660          7 test7
         1      61660          8 test8
         1      61660          9 test9
         1      61661         10 test10
 這裡我準備用1,61658來試驗
 下面使用BBED來進行模擬錯誤:
   (1)安裝BBED目錄在$ORACLE_HOME/rdbms/lib下面使用make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed來進行編譯
   (2)編寫引數檔案bbed.par如下:
     [oracle@b000-vmracdb1 lib]$ more bbed.par
     blocksize=8192
     listfile=list
     mode=edit
   (3)編寫list檔案,裡面放資料檔案列表如下:
     [oracle@b000-vmracdb1 lib]$ more list
1 /oracle_ocfs/oradata/pprac/system01.dbf
2 /oracle_ocfs/oradata/pprac/undotbs01.dbf
3 /oracle_ocfs/oradata/pprac/sysaux01.dbf
4 /oracle_ocfs/oradata/pprac/users01.dbf
5 /oracle_ocfs/oradata/pprac/example01.dbf
6 /oracle_ocfs/oradata/pprac/undotbs02.dbf
   (4)進入BBED使用命令
        bbed parfile=bbed.par  密碼就是blockedit
[oracle@b000-vmracdb1 lib]$ /home/oracle/product/database/rdbms/lib/bbed parfile=bbed.par
Password:

BBED: Release 2.0.0.0.0 - Limited Production on Mon Aug 9 16:52:31 2010

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

************* !!! For Oracle Internal Use only !!! ***************

BBED>
    (5)找到塊命令SET
        BBED> set dba 1,61658
        DBA             0x0040f0da (4255962 1,61658)
    (6)我們來找到以test為開頭的記錄
    BBED> find /c test
 File: /oracle_ocfs/oradata/pprac/system01.dbf (1)
 Block: 61658            Offsets: 2170 to 2681           Dba:0x0040f0da
------------------------------------------------------------------------
 74657374 33202020 20202020 20202020 20202020 20202020 20202020 20202020
 20202020 20202020 20202020 20202020 20202020 20202020 20202020 20202020
 20202020 20202020 20202020 20202020 20202020 20202020 20202020 20202020
 。。。。。。
 這裡看到了第一個test偏移量2170,這個也就是說相對整個塊的一個位置,我也沒有深究。
 然後找到他
 BBED> dump /v dba 1,61658 offset 2170 count 64
 File: /oracle_ocfs/oradata/pprac/system01.dbf (1)
 Block: 61658   Offsets: 2170 to 2233  Dba:0x0040f0da
-------------------------------------------------------
 74657374 33202020 20202020 20202020 l test3          
 20202020 20202020 20202020 20202020 l                
 20202020 20202020 20202020 20202020 l                
 20202020 20202020 20202020 20202020 l                

 <16 bytes="" per="" line="">
 看到了是test123
 然後找下一個
 BBED> f
 File: /oracle_ocfs/oradata/pprac/system01.dbf (1)
 Block: 61658            Offsets: 4179 to 4242           Dba:0x0040f0da
------------------------------------------------------------------------
 74657374 32202020 20202020 20202020 20202020 20202020 20202020 20202020
 20202020 20202020 20202020 20202020 20202020 20202020 20202020 20202020

 <32 bytes="" per="" line="">
偏移量4179
BBED>  dump /v dba 1,61658 offset 4179 count 64
 File: /oracle_ocfs/oradata/pprac/system01.dbf (1)
 Block: 61658   Offsets: 4179 to 4242  Dba:0x0040f0da
-------------------------------------------------------
 74657374 32202020 20202020 20202020 l test2          
 20202020 20202020 20202020 20202020 l                
 20202020 20202020 20202020 20202020 l                
 20202020 20202020 20202020 20202020 l         
 同樣也找到了
 在往下還有test能找到,但是我這裡已經被我修改了,找不到了。
 然後我們修改,弄壞資料塊
 modify 1000 dba 1,61658 這裡是修改的偏移量就是最後找到的TEST*的偏移量我改是test
 修改完成後這個塊就壞了。      
 但是這裡注意由於DB_CACHE_BUFFER的原因會快取資料塊,即使修改了讀取的時候從SGA讀出來的話也不報錯
 需要清空BUFFER或者重啟下,不要讓資料庫快取記憶體快取資料塊。
 然後我們
 SQL> select * from test123 where id=1;
 
        ID NAME
---------- --------------------------------------------------------------------------------
         1 test
 
SQL> select * from test123;
 
select * from test123
 
ORA-01578: ORACLE data block corrupted (file # 1, block # 61658)
ORA-01110: data file 1: '/oracle_ocfs/oradata/pprac/system01.dbf'
錯誤就出來了。
五、如何解決
然後我們就是來解決這個問題,說實話如果是表的資料塊壞了真的沒有太多的辦法,只能先解救我們沒有
損壞塊的資料方法如下:
---有RMAN備份和歸檔的情況下:
這個比較簡單,使用命令
blockrecover datafile 1 block 61658;
就可以了,無需進行不完全恢復。

----沒RMAN備份和歸檔的情況下:
1、設定SKIP
SQL>   begin
  2    dbms_repair.skip_corrupt_blocks(schema_name => 'SYS',object_name => 'TEST123',object_type => DBMS_REPAIR.TABLE_OBJECT,flags => DBMS_REPAIR.SKIP_FLAG);
  3    END;
  4  /
  也就是跳過損壞的塊。
2、檢視下是否是SKIP
SQL> select table_name,skip_corrupt from dba_tables where table_name='TEST123';
 
TABLE_NAME                     SKIP_CORRUPT
------------------------------ ------------
TEST123                        ENABLED
3、再次檢視
SQL> select * from test123;
 
        ID NAME
---------- --------------------------------------------------------------------------------
         4 test4
         5 test5
         6 test6
         7 test7
         8 test8
         9 test9
        10 test10
 木有了壞塊的資料已經沒有了。如果想恢復失去的資料,找找ORACLE SUPPORT,或者資料探勘,反正都是很麻煩的事情,而且不一定行。
 當然如果是索引的壞就重建吧,這個沒事。


如下僅僅記錄一下處理壞塊需要的技術
未標記損壞塊時,未損壞的記錄還能透過RIWID讀出


backup validate database;
select * from v$database_block_corruption;


SELECT e.owner, e.segment_type, e.segment_name, e.partition_name, c.file#
     , greatest(e.block_id, c.block#) corr_start_block#
     , least(e.block_id+e.blocks-1, c.block#+c.blocks-1) corr_end_block#
     , least(e.block_id+e.blocks-1, c.block#+c.blocks-1)
       - greatest(e.block_id, c.block#) + 1 blocks_corrupted
     , corruption_type description
  FROM dba_extents e, v$database_block_corruption c
 WHERE e.file_id = c.file#
   AND e.block_id <= c.block# + c.blocks - 1
   AND e.block_id + e.blocks - 1 >= c.block#
UNION
SELECT s.owner, s.segment_type, s.segment_name, s.partition_name, c.file#
     , header_block corr_start_block#
     , header_block corr_end_block#
     , 1 blocks_corrupted
     , corruption_type||' Segment Header' description
  FROM dba_segments s, v$database_block_corruption c
 WHERE s.header_file = c.file#
   AND s.header_block between c.block# and c.block# + c.blocks - 1
UNION
SELECT null owner, null segment_type, null segment_name, null partition_name, c.file#
     , greatest(f.block_id, c.block#) corr_start_block#
     , least(f.block_id+f.blocks-1, c.block#+c.blocks-1) corr_end_block#
     , least(f.block_id+f.blocks-1, c.block#+c.blocks-1)
       - greatest(f.block_id, c.block#) + 1 blocks_corrupted
     , 'Free Block' description
  FROM dba_free_space f, v$database_block_corruption c
 WHERE f.file_id = c.file#
   AND f.block_id <= c.block# + c.blocks - 1
   AND f.block_id + f.blocks - 1 >= c.block#
order by file#, corr_start_block#;




execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('SYS','TESTER',flags=>dbms_repair.skip_flag);
execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('SYS','TESTER',flags=>dbms_repair.noskip_flag);


11GR2
backup validate database;
RECOVER CORRUPTION LIST;




DRA 11G
backup validate database;
list failure;
advise failure;
repair failure preview;
repair failure;


可以使用下面語法代替RECOVER CORRUPTION LIST;11R2以前
run {blockrecover corruption list;} 


修復單塊


blockrecover datafile 1 block 61658;




ROWID_CREATE函式
     function ROWID_CREATE(rowid_type    IN number,
                           object_number IN number,
                           relative_fno  IN number,
                           block_number  IN number,
                           row_number    IN number)
              return ROWID;

如果是LOB塊的錯誤需要另外的處理的方式
http://blog.itpub.net/7728585/viewspace-1580285/

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-670597/,如需轉載,請註明出處,否則將追究法律責任。

相關文章