ORACLE 壞塊處理

csbwolf10發表於2012-01-29
/*==============================================================
#內容概要:
#  壞快的分類,壞塊形成的原因,如何檢測壞快,修復壞塊,參考文件。
#
#version 1.0
#date:20120124
================================================================*/
 
/*---------------------------------------------------------------
#
#壞塊形成的原因
#
-----------------------------------------------------------------*/

  1)硬體問題
 
     Oracle程式在處理一個資料塊時,首先將其讀入實體記憶體空間,在處理完成後,再由特定程式將其寫回磁碟;
    如果在這個過程中,出現記憶體故障,CPU計算失誤,都會導致記憶體資料塊的內容混亂,最後反映到寫回磁碟的資料塊內容有誤。
    同樣,如果儲存子系統出現異常,資料塊損壞也就隨之出現了。
  
  2)作業系統BUG
 
     由於Oracle程式對資料塊的讀寫,都是以作業系統核心呼叫(system call)的方式完成的,如果作業系統在核心呼叫存在問題,
     必然導致Oracle程式寫入非法的內容。
  
  3)作業系統的I/O錯誤或緩衝問題
  
  4)記憶體或paging問題
  
  5)Oracle軟體BUG
 
     Oracle軟體特定版本上,可能出現導致資料塊的內容出現異常BUG。
  
  6)非Oracle程式擾亂Oracle共享記憶體區域
  
     如上文所述,在當資料塊的內容被讀入主機的實體記憶體時,如果其他非Oracle程式,對Oracle使用的共享記憶體區域形成了擾亂,
     最終導致寫回磁碟的資料塊內容混亂。
  
  7)異常關機,掉電,終止服務
   異常關機,掉電,終止服務使程式異常終止,而破壞資料塊的完整性,導致壞塊產生。

/*---------------------------------------------------------------
#                                  
#壞塊的分類
#
-----------------------------------------------------------------*/
  1)壞塊定義:
    在Oracle資料庫的一個或多個資料塊(一個資料塊的容量在建立資料庫時由db_block_size引數指定,預設為8K)內出現內容混亂的現象。
    由於正常的資料塊都有固定的合法內容格式,壞塊的出現,導致資料庫程式無法正常解析資料塊的內容,進而使資料庫程式報錯乃至掛起,
    並級聯導致整個資料庫例項出現異常。壞塊分為物理壞塊和邏輯壞塊。
  2)物理壞塊
     理壞塊(也可以稱為介質壞塊)指的是塊格式本身是壞的,塊內的資料沒有任何意義。
 
    
  3)邏輯壞塊 
     邏輯壞塊,指的是塊內的資料在邏輯是存在問題。
 
    物理壞塊和邏輯壞塊的分辨方法參見ORACLE DOCUMENT ID 840978.1
   
 
/*---------------------------------------------------------------
#
#檢查壞塊
#簡述發現壞塊的方法
#
-----------------------------------------------------------------*/   
1)使用者操作發現壞塊
   在使用者進行DML時返回錯誤訊息(eg ORA-01578,Ora-111).
  
2) 後臺alert log 中發現壞塊報錯(eg ORA-01578: ORACLE資料塊損壞(檔案號4,塊號35)).
3) DBV 檢查資料庫壞塊,針對資料庫檔案。
   語法如下:
    具體的語法如下:
       關鍵字     說明                    (預設)      
       ----------------------------------------------------      
       FILE        要驗證的檔案                 (無)      
       START       起始塊                    (檔案的第一個塊)      
       END         結束塊                      (檔案的最後一個塊)      
       BLOCKSIZE   邏輯塊大小             (2048)      
       LOGFILE     輸出日誌                     (無)      
       FEEDBACK    顯示進度               (0)      
       PARFILE     引數檔案                 (無)      
       USERID      使用者名稱/口令              (無)      
       SEGMENT_ID  段 ID (tsn.relfile.block) (無)
      
   適用條件及例外:
     
      a. 檢查物理壞塊和邏輯壞塊
      b. 因為dbv要求file後面跟的必須是一個副檔名,所以如果用裸裝置儲存的,就必須使用ln連結裸裝置到一個檔案,
       然後再用dbv對這個連結檔案進行檢查.
      
4) 利用exp工具匯出整個資料庫可以檢測壞塊
   適用條件及例外:
     
      a. HWM以上的壞塊是不會發現的
      b. 索引中存在的壞塊是不會發現的
      c. 資料字典中的壞塊是不會發現的
      d. 檢查物理壞塊
5) ANALYZE   
 
   ANALYZE TABLE tablename VALIDATE STRUCTURE CASCADE
   它執行壞塊的檢查,但是不會標記壞塊為corrupt,檢測的結果儲存在USER_DUMP_DEST目錄下的使用者trace檔案中。
  
   適用條件及例外:
  
      a. 檢查邏輯壞塊

6) rman
   rman 可以在資料庫、表空間、資料檔案級檢測 資料庫壞塊,可以指定檢測物理或者邏輯壞塊,用起來十分方便。
  
   eg.
    BACKUP CHECK LOGICAL VALIDATE DATAFILE n ;(檢測邏輯壞塊)
    BACKUP   VALIDATE DATAFILE n ;(檢測物理壞塊 )
 

/*---------------------------------------------------------------
#
#修復壞塊
#根據不同的情況處理資料庫壞塊。
#
-----------------------------------------------------------------*/
  1)通過上面的檢測方法檢查資料庫的壞塊,也可以通過查詢v$database_currpt_blocks 檢視檢視資料庫現有的壞塊情況。
 
  2)用如下SQL檢查出現壞快的OBJ.
 
    SELECT tablespace_name, segment_type, owner, segment_name, partition_name  FROM dba_extents WHERE file_id = and between block_id AND block_id + blocks – 1;

     
  3)儲存除壞塊以外的其他資料
 
    a)利用以上查處的rowid 建備份表儲存資料。
     
       A)先取得壞塊中ROW ID的最小值,執行以下的語句:            
                                                                         
         SELECT dbms_rowid.rowid_create(1,,,,0) from DUAL; 
                                                                         
       B)取得壞塊中的ROW ID的最大值,執行以下的語句:                       
                                                                         
         SELECT dbms_rowid.rowid_create(1,,,+1,0) from DUAL;
        
       C)儲存資料
 
        INSERT INTO salvage_table SELECT /*+ ROWID(A) */ * FROM A WHERE rowid < '';
        INSERT INTO salvage_table SELECT /*+ ROWID(A) */ * FROM A  WHERE rowid >= '‘;
       
    b)通過設定 ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10'; 在session 級別跳過壞塊,建立備份表。
   
        create table salvage_table as select * from owner.tablename.
       
      通過設定alter session set events='10231 trace name context off' 終止event.     
      10231 trace 也可以在系統級設定,整個系統都會忽略壞塊。
     
    c)通過呼叫 DBMS_REPAIR 包來標記壞塊並跳過壞塊
     
      A) exec DBMS_REPAIR.ADMIN_TABLES('REPAIR_TABLE',1,1,'USERS');
         exec DBMS_REPAIR.ADMIN_TABLES('ORPHAN_TABLE',2,1,'USERS');
        
      B)
         Set serveroutput on;
         DECLARE
           cc NUMBER;
         BEGIN
           DBMS_REPAIR.check_object(schema_name=>'SYS',--注意此處是使用者名稱
                                     object_name    =>'DMM',
                                     corrupt_count  =>cc);
           DBMS_OUTPUT.put_line(TO_CHAR(cc));
         END;
      C)
    DECLARE cc  NUMBER;
    BEGIN
      DBMS_REPAIR.fix_corrupt_blocks(schema_name  =>'SYS',
                                      object_name  =>'DMM',
                                      fix_count    =>cc);
      DBMS_OUTPUT.put_line(a=>TO_CHAR(cc));
    END;
      D)execdbms_repair.skip_corrupt_blocks(schema_name=>'SYS',object_name=>'DMM',flags=>1);
        
      create table salvage_table as select * from owner.tablename. 
      
        
  4)修復壞塊
             
    a)有恢復整個檔案,備份和LOG,資料庫在歸檔模式。
   
      A) 先offline受影響的資料檔案,執行以下的語句:
       ALTER DATABASE DATAFILE 'name_file' OFFLINE;
      B) 保留有壞塊的資料檔案,然後拷貝備份的資料檔案。如果恢復的資料檔案要求路徑不同,執行以下的語句:
         ALTER DATABASE RENAME FILE 'old_name' TO 'new_name';
      C) 恢復資料檔案,執行以下語句:
         RECOVER DATAFILE 'name_of_file';
        
      D) Online恢復後的資料檔案,執行以下的語句:
         ALTER DATABASE DATAFILE 'name_of_file' ONLINE;
        
    b)只恢復單個塊,要求資料庫版本是9.2.0以上,要求配置了Rman的catalog資料庫,資料庫為歸檔方式,並且有完整的物理備份。
   
        Rman>run{blockrecover datafile 5 block 11,16;}
      
       
    c)沒有備份和歸檔,丟失損壞的資料。如果業務能通過別的途徑找出丟失的資料也可以恢復。
   
      A) truncate 該表,再用儲存的這個表的其他資料重建這張表。
     
       truncate table owner.table_name
       create tabale owner.table_name as select * from owner.table_name_bak.
      
      B)如果是索引在重建之前需要備份索引的統計資訊,重建之後恢復統計資訊。
     
        exec dbms_stats.create_stat_table(ownname => 'YYYY',stattab => 'temp_stat_table_20120115');
    exec dbms_stats.export_index_stats(ownname => 'YYYY',indname => 'IND_GM_PREM_NAS_POLNO',stattab => 'temp_stat_table_20120115',statown => 'YYYY');
    
    ALTER INDEX YYYY.IND_GM_PREM_NAS_POLNO REBUILD parallel 12;
    
    exec dbms_stats.import_index_stats(ownname => 'YYYY',indname => 'IND_GM_PREM_NAS_POLNO',stattab => 'temp_stat_table_20120115',statown => 'YYYY',no_invalidate => true,force => true);
 
 

 

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

相關文章