對Oracle數據庫壞塊的理解

1.物理壞塊和邏輯壞塊

      在數據庫中有一個概念叫做數據塊的一致性,Oracle的數據塊的一致性包括了兩個層次:物理一致性和邏輯一致性,如果一個數據塊在這兩個層次上存在不一致性,那就對應到了我們今天要要說的物理壞塊和邏輯壞塊。

      在每一個數據塊的頭部有一個校驗和字段,每當數據塊要被寫回磁盤前,Oracle都會重新計算 這個數據塊的校驗和,並記錄到這個字段最終寫會磁盤。下次數據塊被讀入內存,Oracle會重新 計算數據塊的校驗和,並和塊頭的字段相比較,如果有差異,Oracle就知道這個數據塊有錯誤, 會報出ORA-1578錯誤。    通過校驗和字段進行的檢查就是物理一致性檢查,這個功能可以讓Oracle檢查到所有底層的錯誤, 包括磁盤、存儲、IO子系統,所以稱做物理一致性檢查。

     在Oracle中每當要修改一個數據塊中,會先對數據塊內容做一個一致性檢查(如檢查記錄 是否被不存在的食物鎖定、記錄和索引是否對應等)。如果這種一致性檢查失敗,就會拋出 ORA-600的Internal錯誤。當Oracle檢查到數據塊的邏輯一致性時,會嘗試對數據塊做 Cache Recovery,如果不能把數據塊恢復到一致狀態,Oracle就會把這個數據塊標誌爲 Software Corrupt,當有查詢訪問到這數據塊時,也會拋出前面ORA-1578錯誤。

      物理一致性檢查利用校驗和字段工作,主要側重於檢查硬件故障,並不關心內容正確與否, 而邏輯一致性檢查就是側重於內容的檢查,內容檢查要比校驗和檢查複雜的多。 邏輯一致性檢查內容要多於物理一致性檢查。

 

2.發生壞塊的原因

       造成數據塊損壞的原因多種多樣,可是因爲物理原因導致,也可能人爲原因或Oracle bug導致。比較常見的人爲原因異常關機、掉電、終止服務使進程異常終止,從而破壞數據的完整性,導致壞塊的產生。發生數據塊損壞的原因時,最典型的表現是遇到ORA-01578錯誤(比如在全表掃描時),有時也可能是ORA-600內部錯誤。

 

3.檢查數據塊的一致性

    (1)使用初始化參數檢查數據塊的一致性

     通過設置初始化參數db_block_checksum=true/false來啓用、關閉物理一致性檢查,啓用該參數這會 增加1%~2%的負載,Oracle推薦啓用該參數。在Oracle9i、10g中,默認是啓用的。

     通過設置參數db_block_checking=true可以啓用數據塊的邏輯一致性檢查。啓用該參數這會 增加1%~10%的負載,尤其DML操作越密集性能影響越大。在Oracle10g中這個參數 默認值是false,這將意味這數據庫只對System表空間做邏輯一致性檢查。

 

    (2)DBV工具對數據塊物理/邏輯性檢查

   詳情:http://book.51cto.com/art/201108/287893.htm

 

    (3)analyze命令檢查數據塊一致性

     analyze命令有很多中用法,可以完成很多功能,具體可參考:http://blog.csdn.net/tianlesoftware/article/details/7055164

     analyze命令檢查對象一致性:   analyze table tablename validate structure cascade online(offline);

     該命令同樣會執行物理和邏輯一致性檢查。除此之外,它還會檢查表和索引條目的匹配性,檢查分區表的記錄是否在正確的分區中, 檢查出的問題會放在USER_DUMP_DEST目錄的trace文件中。

      使用該命令注意一下幾個問題:

      *當檢查分區表的記錄是否在正確的分區時,可以把檢查出來的記錄的ROWID記錄在一個特殊表中,這個表叫做invalid_rows,該表需要   使用utlvalid.sql腳本提前建立,檢查語法:   analyze tablename validate structure into invalid_rows;  

      *如果檢查索引,這個命令會檢查數據塊和索引的一致性,但是不會確認每條記錄都有相應的索引項或這索引有對應的記錄,  如果需要這種檢查,需要使用cascade關鍵字。  

      *如果使用online子句,可以在DML操作時在線檢查一致性,只是這時不會收集對象的統計信息;而如果使用offline表會被鎖住。

 

    (4)使用rman工具檢查

     *檢查數據文件
      backup check logical validate [database];
 
     *檢查單個數據文件
      backup check logical validate datafile 1,2;
 
     *檢查整個庫
      backup check logical validate database    檢查的結果放在v$database_block_corruption這個動態視圖中。

      *這個命令對系統性能有一定的影響。

 


     (5)使用dbms_repair.check_object方法執行檢查
      詳細可參考:http://blog.itpub.net/8494287/viewspace-1357457/

 

  (6)利用exp工具導出整個數據庫可以檢測壞塊


    導出命令在執行中會報ORA-01578錯誤,在這錯誤提示中會提示那個文件號的文件以及這個文件中的哪個塊被損壞,如:ORA—01578:ORACLE 數據塊損壞(文件號 4,塊號 35)。利用exp工具進行檢查壞塊也侷限性,對一些類型的壞塊是檢測不出來的如:HWM以上的壞塊是不會發現的、索引中存在的壞塊是不會發現的、數據字典中的壞塊是不會發現的。

 

4.使用BBED模擬壞塊

   http://www.cnblogs.com/myrunning/p/4433150.html

 

5.壞塊的恢復理論

       對於發生數據塊不一致的數據塊,如果當前數據庫有備份且處於歸檔模式,那麼就可以利用rman工具數據塊恢復功能對數據塊進行恢復,這種方法最簡單有效,而且可以在數據文件在線時進行,不會發生數據丟失。對於沒有備份的數據庫發生數據塊損壞,可能會發生數據的丟失或數據不丟失,這要根據發生壞塊的所在的對象決定的,如索引塊發生損壞,數據就不會丟失,重建索引就可以了,發生數據丟失的多發生在表或分區表數據塊上。

 

5.1.不丟數據的恢復方法

    利用rman工具:

        blockrecover datafile xx block yy;--修復單個壞塊

        blockrecover corruption list;--修復全部壞塊

如果壞塊上的表最近都沒有更新,還可以利用bbed的copy命令來從一個最近的備份中copy過來一個數據塊恢復,具體不演示。

 

5.2.可能會丟數據的恢復方法

    5.2.1 確認壞塊類型

        當一個壞塊發生時,我們首先要確認這個塊到底是什麼樣的塊,是普通表的數據塊(分區表的上數據塊)、索引塊等,針對不同的壞塊類型我們來確認不同的恢復方法。

 

      <1>確定文件號

       Oracle有兩種數據文件號來標識數據文件。絕對文件號(Absolute File#  AFN)和相對文件號(Relative File# RFN)。AFN是數據文件在整個系統範圍內的編號,而RFN是數據文件在表空間範圍內的編號。兩個文件可能有相同的RFN,但是不會有相同的ASN。在ORA-01578中提示的文件號是RFN,在ORA-1110中提示的文件號是AFN,在ORA-600中提示的文件號爲AFN,從視圖中看到的文件號、數據塊號屬於哪個segment 使用的也是AFN 。

複製代碼
SQL> select tablespace_name,file_id "AFN",relative_fno "RFN"
  2  from dba_data_files;

TABLESPACE_NAME                       AFN        RFN
------------------------------ ---------- ----------
USERS                                   4          4
SYSAUX                                  3          3
UNDOTBS1                                2          2
SYSTEM                                  1          1
EXAMPLE                                 5          5
LIVAN_TBS                               6          6

6 rows selected.
複製代碼

 

SQL> select tablespace_name,file_id "AFN",relative_fno "RFN"
  2  from dba_temp_files;

TABLESPACE_NAME                       AFN        RFN
------------------------------ ---------- ----------
TEMP                                    1          1

 


        --利用AFN查詢文件
        select name from v$datafile where file#=&AFN;

 


    <2>確認損壞數據塊的類型

複製代碼
set lines 120
col segment_name for a20
col partition_name for a20
col owner for a10

select segment_name,partition_name,segment_type,owner,tablespace_name
from sys.dba_extents
where file_id=&AFN
and &bad_block_id between block_id and block_id + blocks-1;
複製代碼


 

   5.2.2按照不同的類型設置不同的恢復策略

 

     <1>用戶表

        對於損害的數據塊屬於用戶表的,數據丟失時不可避免的,這時需要做的就是把其他數據塊中的數據搶救出來,而受損數據塊的數據就永久丟失了。這時的恢復策略是儘可能的減少用戶的損失。(如果這種數據損失不能接受,就必須考慮其他特殊手段來嘗試恢復受損數據塊中的數據)這種情況我們可以採用兩種辦法:
       *放棄壞塊上的數據,搶救其他數據塊上的數據,並重建對象;
       *把數據快標記爲skiped,然後放任不管,也就是給這個數據塊打上個標籤,這樣以後所有的操作都會跳過這個數據塊。

 

       在處理數據表的壞塊時,也要考慮關聯對象的後續處理:

  --索引

select owner,index_name,index_type
from dba_indexes
where table_owner='&owner' and table_name='&semeng_name';

 

如果因爲數據快損壞導致記錄丟失,那麼這些索引也就失效了,應該被刪除,然後重建索引。

 

  --主鍵

     Oracle通過對主鍵字段創建唯一索引來實現主鍵約束,所以主鍵的處理方式和索引的處理方式一樣,重建這個唯一索引。

select owner,constraint_name,constraint_type,table_name
from dba_constraints
where owner='&owner' and table_name='&segment_name' 
and constraint_type='P';

 

--指向該主鍵的外鍵

查詢出指向該主鍵的外鍵,主鍵外鍵處理方法相同,都需要重建索引。

select owner,constraint_name,constraint_type,table_name
from dba_constraints
where r_owner='&owner' and r_constraint_name='&constraint_name';

 

     <2>分區表

    分區表的處理和普通表類似,確認數據屬於哪個分區,然後對受損的分區可以通過exchange操作,和一個相同表結構的空表進行交換,不影響程序的正常運行,然後與普通表相同的方法處理。

 

    
      <3>索引

      如果受損對象爲索引,直接刪除索引重建就可以了。

     對於普通表索引重建需要使用 alter index ... rebuild online語法,如果不帶online關鍵字, 會依據舊的索引(包含壞塊的)重建索引。 對於分區表索引,可以使用alter index xxx rebuild partition yyy的語句,因爲分區索引的 重建不會使用舊索引,所以可以不加online關鍵字。

 

  索引壞塊注意以下:

 ---確認索引所屬的表

 select table_owner,table_name
from dba_indexes 
where owner='&owner'  and index_name='&segment_name';

 

 

--如果是分區索引,查看屬於分區

select partition_name
from dba_extents
where file_id=&AFN
and &bad_block_id between block_id and block_id + blocks-1;

 

--確認這個索引是否用於某個約束

select owner,constrint_name,constraint_type,table_name
from dba_constraints 
where owner='&table_owner'
and constraint_name='&index_name';

 

--如果這個索引是主鍵索引,確認是否有外鍵指向這個索引

select owner,constraint_name,constraint_type,table_name
from dba_constraints
where r_owner='&owner' and r_constraint_name='&constraint_name';

 

 

   5.2.3恢復數據

       恢復數據就是把其他好的數據塊中的數據全部搶救出來。簡單地說就是把手損數據塊標識成"software corrupt", 然後讓Oracle做全表掃描時跳過這些塊,而不是拋出異常,從而通過CTAS(create table xx as select ...)方法把數據搶救出來。

      要想讓Oracle做全表掃描時跳過這些塊(前提是先被打上"software corrupt"標記),可以使用兩種方法: 使用dbms_repair包或使用10231事件。

     如果遇到ORA-1578錯誤,說明數據塊已經被標識爲"software corrupt"。如果是其他錯誤如ORA-600,就說明損壞的數據塊還沒有被標識爲"software corrupt"。

      查看數據壞快是否被標記爲"software corrupt",可以通過DBMS_REPAIR.CHECK_OBJECT方法檢查後查詢REPAIR_TABLE表,如果數據塊已經被標識成"software corrupt",那麼 REPAIR_TABLE 表 marked_corrupt列爲true,repair_description 列沒內容。如果數據塊沒有被標識成"software corrupt",REPAIR_TABLE 表 marked_corrupt列爲FALSE,repair_description列會提示"mark block software corrupt",也就是需要把數據塊標識爲"software corrupt"。

     當數據塊被標識爲"software corrupt"後,就可以利用 dbms_repair.skip_corrupt_blocks或者10231事件對segment做一個
標誌,代表掃描該對象時如果遇到"software corrupt"的數據塊可以直接跳過,而不是拋出ORA-01578錯誤終止,這樣就可以完成對所有好的數據塊的掃描,實現搶救數據。從視圖dba_tables.skip_corrupt字段可以看出表是否設置了這個標誌。

    ###dbms_repair方法

        設置標誌:exec dbms_repair.skip_corrupt_block(<schema>,<tablename>);
        設置完標識後再掃描到數據就不會提示錯誤,而是會在log日誌中記錄一條條目:
        table scan:segment file# 6 block# 4 skipping corrupt block file#6 block# 5
        清除標誌:exec dbms_repair.skip_corrupt_block(<schema>,<tablename>,flags=dbms_repair.noskip_flag);

      ###使用10231事件

      會話級別設置:alter session set events '10231 trace name context forever,level 10';

       通過初始化參數在實例級別設置:event="10231 trace name context forever,level 10";

 

 

5.壞塊恢復實例

http://www.cnblogs.com/myrunning/p/4525917.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章