對oracle中出現的壞塊的處理方法

不一樣的天空w發表於2018-01-06

這篇文章介紹在oracle資料檔案中出現一個或多個資料塊壞塊時的處理方法.當出現資料塊壞塊出誤時對於每一個壞塊都提供了以下資訊:
1.包含這個壞塊的資料檔案的絕對檔案號可以標示為"AFN".
2.包含這個壞塊的資料檔案的檔名可以標示為"FILENAME"(如果知道檔案號但不知道檔名那麼可以執行select name from v$datafile where file#=&AFN來得到檔名,如果檔案號在v$datafile中沒有記錄且AFN比引數db_files引數的值還大那麼這個檔案可能是臨時檔案.如果是這種情況可以執行select name from v$tempfile where file#=(&AFN-&DB_FILES_value)
3.資料檔案中壞塊的塊號可以標示為"BL"
4.受壞塊影響的表空間號和表空間名稱可以標示為"TSN"和"TABLESPACE_NAME".可以執行select ts# "TSN" from v$datafile where file#=&AFN;select tablespace_name from dba_data_files where file_id=&AFN來查詢.
5.出現壞塊的表空間的資料塊大小可以標示為"TS_BLOCK_SIZE".對於oracle9i來說可以執行select block_size from dba_tablespace where tablespace_name=(select tablespace_name from dba_data_files where file_id=&AFN);來查詢資料塊大小.對於oracle7.8.0和8.1在資料庫中每一個表空間都有相同的資料塊大小.對於這些版本可以使用show parameter db_block_size來顯示資料塊大小.

例如:ora-1578錯識資訊
ORA-01578: ORACLE data block corrupted (file # 7, block # 12698)
ORA-01110: data file 22: /oracle1/oradata/V816/oradata/V816/users01.dbf
從上面的錯識資訊可知:絕對檔案號AFN是22,相對檔案號RFN是7,資料塊BL是12698,檔名FILENAME是/oracle1/oradata/V816/oradata/V816/users01.dbf,表空間號和表空間名可以用上面的查詢得到.

處理壞塊的步驟
導致壞塊的原因有許多種例如:
壞的 IO 硬體/韌體
OS 問題
Oracle 問題
對於執行過“UNRECOVERABLE”或“NOLOGGING”操作的資料庫進行恢復在這種情況下可能產生 ORA-1578 錯誤

在遇到壞塊時,我們通常無從瞭解根本原因,並且在大多數情況下,當前最迫切的是重新啟動資料庫並使其執行起來.
1. 確定壞塊問題的範圍,並確定這些問題是永續性問題還是暫時性問題
如果問題涉及範圍很大,或錯誤不穩定,則關鍵在於先識別原因(檢查硬體等).這點很重要.因為如果是底層硬體出現錯誤.恢復系統便毫無意義

2.更換或拆下任何有問題的或可疑的硬體

3.確定受到影響的資料庫物件有哪些

4.選擇最合適的資料庫恢復/資料搶救選項

確定壞塊問題的範圍
每次發生壞塊錯誤時,都應記下完整的錯誤訊息,並檢視該例項的告警日誌和跟蹤檔案,以瞭解任何相關的錯誤.首先進行這些步驟非常重要,這可以評估該損壞是單個塊,還是由於UNRECOVERABLE操作產生的錯誤,或是更嚴重的問題.

使用DBVERIFY掃描受影響的檔案以及一切重要的檔案也是不錯的辦法,這樣可以檢查是否有其他壞塊,從而確定問題的範圍.一旦確定了損壞的檔案/塊組合列表,即可使用以下步驟來幫助確定應採取何種措施:
1.完整記錄初始錯誤,以及發生錯誤的應用程式的詳細資訊
2.及時地儲存從告警日誌中首次 (FIRST) 記錄到問題前數小時到當前時間點所提取的內容
3.儲存告警日誌中提到的任何跟蹤檔案
4.記錄最近遇到的任何 OS 問題
5.記錄是否正在使用任何特殊功能,例如:ASYNC IO、快速寫入磁碟選項等
6.記錄當前的備份位置(日期、型別等)
7.記錄資料庫是否處於ARCHIVELOG 模式,例如:在SQL*Plus(或 Server Manager)中執行“ARCHIVE LOG LIST”

更換或拆下可疑硬體
大多數壞塊問題是由故障硬體導致的.如果出現硬體錯誤或可疑元件,最好進行修復,或者在執行恢復操作之前,確保在單獨的磁碟子系統上有足夠的可用空間用於恢復,您可以使用以下步驟移動資料檔案:
1.確保要遷移的檔案已離線或資料庫例項處於 MOUNT 狀態(未開啟)
2. 將該資料檔案物理還原(或複製)到新位置 例如:/newlocation/myfile.dbf
3.將該檔案的新位置告知 Oracle.
例如:ALTER DATABASE RENAME FILE '/oldlocation/myfile.dbf' TO '/newlocation/myfile.dbf';
(請注意,您不能對臨時檔案進行重新命名,而應刪除臨時檔案並在新位置重新建立)
4.使相關資料檔案/表空間上線(如果資料庫已開啟)

注意:
如果存在多個錯誤(不是由於 NOLOGGING操作導致的)或受影響檔案所在的OS層面出現錯誤或錯誤是暫時性的且遊離不定,那麼,如果不解決底層問題或準備另外的磁碟空間,那麼進行任何操作都是毫無意義的.

如果使用了任何特殊IO選項,例如direct IO,async IO或類似的選項,最好將其禁用,以消除這些選項成為潛在問題原因的可能性

確定受影響的物件有哪些
在決定如何恢復之前,最好先確定哪些物件受到了影響,因為壞塊可能發生在那些容易被重新建立的物件中.例如,對於只有5行資料的表中發生的壞塊,刪除並重新建立表可能要比執行恢復快得多.

對於每個壞塊,請收集下表中的資訊.進行此操作的步驟如下所述。
1.初始錯誤
2.絕對檔案號AFN
3.相關檔案號RFN
4.塊編號BL
5.表空間
6.段型別
7.段所有者.名稱
8.相關物件
9.恢復選項

在Oracle8/8i/9i/10g中;絕對檔案號和相關檔案號通常是一樣的,但也可能不同(尤其是在資料庫是由Oracle7遷移而來的情況下).要獲得正確的AFN和RFN編號,否則您可能最終搶救的是錯誤的物件.

下列查詢將顯示資料庫中資料檔案的絕對和相關檔案號:
SELECT tablespace_name, file_id "AFN", relative_fno "RFN" FROM dba_data_files;

在Oracle8i/9i/10g中:除了上述關於Oracle8 的說明外,從 Oracle8i開始將擁有臨時檔案.下列查詢將顯示資料庫中臨時檔案的絕對和相關檔案號:
SELECT tablespace_name, file_id+value "AFN", relative_fno "RFN"
FROM dba_temp_files, v$parameter WHERE name='db_files';

在Oracle7中:“絕對檔案號”和“相關檔案號”使用相同的檔案號

“段型別”,“所有者”,“名稱”和“表空間”
在給定壞塊的絕對檔案號“&AFN”和塊編號“&BL”的情況下,下列查詢將顯示物件的段型別,所有者和名稱,資料庫必須開啟才能使用此查詢:
SELECT tablespace_name, segment_type, owner, segment_name
FROM dba_extents
WHERE file_id = &AFN
and &BL between block_id AND block_id + blocks - 1;

如果壞塊位於臨時檔案中,則上述查詢將不會返回任何資料,對於臨時檔案,“段型別”應為“TEMPORARY”

如果上述查詢未返回行,也可能是因為壞塊是本地管理表空間 (Locally Managed Tablespace, LMT)中的段頭.當壞塊為LMT中的段頭塊時,上述查詢將在alert.log 中生成一個壞塊訊息,但查詢不會失敗.在這種情況下,請使用以下查詢:
SELECT owner, segment_name, segment_type, partition_name
FROM dba_segments
WHERE header_file = &AFN and header_block = &BL;

按段型別分類的“相關物件”和可能的“恢復選項”:
相關物件和能夠使用的恢復選項取決於SEGMENT_TYPE.對於各種最常見的段型別,其他查詢和可能的恢復選項如下所示:
CACHE
如果段型別為 CACHE,請再次檢查您是否輸入了正確的 SQL語句 和引數。
恢復選項:可能需要恢復資料庫。

CLUSTER
如果段型別為 CLUSTER,則應確定它包含哪些表。
例如:
SELECT owner, table_name
FROM dba_tables
WHERE owner='&OWNER'
AND cluster_name='&SEGMENT_NAME';

恢復選項:
如果所有者為“SYS”可能需要恢復資料庫。

對於非資料字典cluster,可能的選項包括:
恢復或 搶救cluster中所有表的資料,然後重新建立cluster及其所有表,
cluster可能包含多個表,因此在做出決策之前,最好先收集cluster中每個表的資訊。

INDEX PARTITION
如果段型別為INDEX PARTITION,請記錄名稱和所有者,然後確定哪些分割槽受到影響:
SELECT partition_name
FROM dba_extents
WHERE file_id = &AFN
AND &BL BETWEEN block_id AND block_id + blocks - 1;
然後按照處理INDEX段的步驟繼續下面的操作.
恢復選項:
使用下列語句可以重建索引分割槽:
ALTER INDEX xxx REBUILD PARTITION ppp;

INDEX
如果段型別為INDEX,對於非字典INDEX或INDEX PARTITION,確定索引位於哪個表中:
例如:
SELECT table_owner, table_name
FROM dba_indexes
WHERE owner='&OWNER'
AND index_name='&SEGMENT_NAME';
並確定索引是否支援約束:
例如:
SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints
WHERE owner='&TABLE_OWNER'
AND constraint_name='&INDEX_NAME';

CONSTRAINT_TYPE 的可能值包括:
P 索引支援主鍵約束。
U 索引支援唯一約束。
如果索引支援主鍵約束(型別“P”),則確認主鍵是否被任何外來鍵約束引用:
例如:
SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints
WHERE r_owner='&TABLE_OWNER'
AND r_constraint_name='&INDEX_NAME'
選項:
如果所有者為“SYS”,可能需要恢復資料庫。
對於非字典索引,可能的選項包括:
恢復或 重建索引(任何相關聯的約束會隨之禁用/啟用)

ROLLBACK
如果段型別為ROLLBACK,因為 ROLLBACK 段壞塊需要特殊處理。
選項可能需要恢復資料庫。

TYPE2 UNDO
TYPE2 UNDO 是系統管理的undo段,它是 rollback段的一種特殊形式.這些段的壞塊需要特殊處理.
選項可能需要恢復資料庫。

TABLE PARTITION
如果段型別為TABLE PARTITION,請記錄名稱和所有者,然後確定哪些分割槽受到影響:
SELECT partition_name
FROM dba_extents
WHERE file_id = &AFN
AND &BL BETWEEN block_id AND block_id + blocks - 1;
然後按照處理TABLE段的步驟繼續下面的操作.
選項:
如果所有壞塊均位於同一個分割槽,則此時可以採取的一個做法是用一個空表EXCHANGE壞塊所在的分割槽,這可以讓應用程式繼續執行(無法訪問壞塊所在的分割槽中的資料),然後可以從之前的空表中提取任何未損壞的資料

TABLE
如果所有者為“SYS”,可能需要恢復資料庫。
對於非字典 TABLE 或 TABLE PARTITION,確定表中存在哪些索引:
例如:
SELECT owner, index_name, index_type
FROM dba_indexes
WHERE table_owner='&OWNER' AND table_name='&SEGMENT_NAME';
並確定表中是否存在任何主鍵:
例如: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';
選項:
如果所有者為“SYS”,可能需要恢復資料庫。
對於非字典表,可能的選項包括:
恢復或 搶救表(或分割槽)中的資料,然後重新建立表(或分割槽)或忽略壞塊(例如:使用DBMS_REPAIR標記需要跳過的問題塊)

IOT(索引組織表)
IOT 表中的壞塊應按照表或分割槽表中的處理方式來處理。
唯一的例外是如果 PK 損壞。
IOT表的PK就是表本身它不能被刪除和重新建立
選項:
如果所有者為“SYS”,可能需要恢復資料庫。
對於非字典表,可能的選項包括:
恢復或 搶救表(或分割槽)中的資料,然後重新建立表(或分割槽)或忽略壞塊(DBMS_REPAIR不適用於IOT)

LOBINDEX
確定LOB屬於哪個表:
SELECT table_name, column_name
FROM dba_lobs
WHERE owner='&OWNER' AND index_name='&SEGMENT_NAME';
如果表的所有者為“SYS”可能需要恢復資料庫。
不可以重建 LOB 索引,因此您必須將該問題作為受影響的表中LOB列上的壞塊來處理。
選項:
如果所有者為“SYS”可能需要恢復資料庫。
對於非字典表,可能的選項包括:
恢復或 搶救表(及其 LOB 列)中的資料,然後重新建立表,忽略壞塊的做法通常不可取,除非不大可能對錶中的問題列執行任何進一步的 DML 操作。

LOBSEGMENT
確定 LOB 屬於哪個表:
例如:
SELECT table_name, column_name
FROM dba_lobs
WHERE owner='&OWNER'
AND segment_name='&SEGMENT_NAME';
如果表的所有者為“SYS”,可能需要恢復資料庫。
對於非字典表,要查詢引用損壞的 LOB 塊的具體行可能比較困難,因為報告的錯誤中不會顯示錶中的哪一行資料包含損壞的 LOB 資料。
通常可以參考發生該錯誤的應用程式日誌、任何SQL_TRACE、會話的10046 跟蹤檔案(如果有),或透過在會話中設定事件“1578 trace name errorstack level 3”,檢視是否有助於標識當前的 SQL/繫結/行。
例如:
ALTER SYSTEM SET EVENTS '1578 trace name errorstack level 3';
然後等待應用程式觸發該錯誤,並查詢跟蹤檔案。
如果沒有任何線索,您可以構建 PLSQL 塊,逐行掃描問題表以提取 LOB 列資料,掃描將一直迴圈進行,直至發生錯誤。此方法可能需要一段時間,但它應該可以找到引用了損壞的 LOB 塊的資料行的主鍵或 ROWID。
例如:
set serverout on
exec dbms_output.enable(100000);
declare
error_1578 exception;
pragma exception_init(error_1578,-1578);
n number;
cnt number:=0;
badcnt number:=0;
begin
for cursor_lob in (select rowid r, &LOB_COLUMN_NAME L
from &OWNER .. &TABLE_NAME) loop
begin
n := dbms_lob.instr(cursor_lob.L, hextoraw('AA25889911'), 1, 999999);
exception
when error_1578 then
dbms_output.put_line('Got ORA-1578 reading LOB at ' ||
cursor_lob.R);
badcnt := badcnt + 1;
end;
cnt := cnt + 1;
end loop;
dbms_output.put_line('Scanned ' || cnt || ' rows - saw ' || badcnt ||
' errors');
end;
/
損壞的 LOB 塊可能僅顯示為舊版本(為保證一致性讀取),且該塊未被重新使用,在這種情況下,所有表中所有行都可以訪問,但一旦該塊被回收重新使用,就不可以插入/更新 LOB 列了。
選項:
如果所有者為“SYS”,可能需要恢復資料庫。
對於非字典表,可能的選項包括:
恢復或搶救表(及其 LOB 列)中的資料,然後重新建立表或忽略壞塊(不可以在 LOB 段上使用 DBMS_REPAIR)

TEMPORARY
如果段型別為TEMPORARY,則壞塊不會影響永久物件.檢查發生問題的表空間是否正在被用作TEMPORARY表空間:
SELECT count(*) FROM dba_users
WHERE temporary_tablespace='&TABLESPACE_NAME';
選項:
如果是 TEMPORARY_TABLESPACE,則可能可以建立新的臨時表空間,並將所有使用者切換到該表空間,然後刪除有問題的表空間。
如果不是臨時表空間,則該塊不會再被讀取,而且會在下次使用時被重新格式化 — 如果問題的根本原因已經得到解決,則不應再發生該錯誤。
通常情況下,不需要進行任何還原,但如果磁碟可能有問題,且表空間包含有用資料,則最好對資料庫中受影響的檔案進行恢復

“無返回行”
如果沒有包含壞塊的extent,則首先再次檢查查詢中使用的引數.如果您確定檔案號和塊編號是正確的,且不屬於 DBA_EXTENTS 中的某個物件,則執行以下操作:
再次檢查相關檔案是否為臨時檔案。請注意,臨時檔案的檔案號取決於資料庫初始化引數 DB_FILES,因此對該引數的任何更改都會改變錯誤中報告的絕對檔案號。

DBA_EXTENTS 不包含本地管理表空間中用於本地空間管理的塊

如果您在資料庫執行查詢語句的時間點與出錯的時間點不相同,那麼問題物件可能已經被刪除,因此針對 DBA_EXTENTS 的查詢可能不會顯示任何行。

如果您正在調查的錯誤由 DBVERIFY 報告,則 DBV 將檢查所有塊,而不管它們是否屬於某個物件。因此,壞塊可能存在於資料檔案中,但卻未被任何物件使用。
選項:
未使用的 Oracle 塊上的錯誤可以忽略,因為如果需要使用該塊,Oracle 會建立新的塊映像(格式化),因此,該塊上的任何問題將永不會被讀取。
如果您懷疑該塊可能是空間管理塊,則可以使用 DBMS_SPACE_ADMIN 包來幫助您進行檢查:
exec DBMS_SPACE_ADMIN.TABLESPACE_VERIFY('&TABLESPACE_NAME');
以上命令會將不一致寫入跟蹤檔案,但如果遇到致命的壞塊,它將報告如下錯誤:
ORA-03216: Tablespace/Segment Verification cannot proceed
點陣圖空間管理塊上發生的錯誤通常可以透過執行以下命令來修正:
exec DBMS_SPACE_ADMIN.TABLESPACE_REBUILD_BITMAPS('&TABLESPACE_NAME');
對於每個壞塊,如果需要嘗試並確定實際壞塊原因,則收集如下物理證據也是一個比較好的方法:
i) 壞塊及位於其任意一側的塊的作業系統 HEX 轉儲。
在 UNIX 上:
dd if=&FILENAME bs=&TS_BLOCK_SIZE skip=&BL-1 count=3 of=BL.dd
例如:對於BL=1224:
dd if=ts11.dbf bs=4k skip=1223 count=3 of=1223_1225.dd
在 VMS 上:
其中 XXXX=作業系統塊編號(512 位元組塊中)
要計算此值,用報告的塊編號乘以“&TS_BLOCK_SIZE/512”。

ii) 處於 ARCHIVELOG 模式時,複製出錯時間前後的歸檔日誌檔案的安全副本,最好包括報告錯誤前數小時的日誌檔案。並且,儲存問題資料檔案在出錯前的所有副本,因為之前的資料檔案映像以及 redo 記錄有助於找出錯誤原因DBV 通常可用於檢查問題是否存在於檔案的備份副本中).理想的情況是獲得沒有報告壞塊的資料檔案備份映像,以及從該時間點開始到首次報告壞塊時間之後不久的時段內的所有 redo 記錄。

iii) 獲得問題塊的 Oracle 轉儲:
ALTER SYSTEM DUMP DATAFILE '&FILENAME' BLOCK &BL;

(4) 選擇恢復選項

現在,最佳的恢復選項取決於受影響的物件。前面第 (3) 部分中的說明應該已經重點介紹了針對每個受影響物件的主要可用選項。選擇的實際恢復方法可能包含以下一種或多種混合方法:
是否需要進行任何恢復操作?
如果錯誤發生在TEMPORARY 表空間中,或位於不再屬於任何資料庫物件的塊中,則無需進行任何操作.

可以使用完全恢復嗎?
要選用完全恢復,必須滿足如下條件:
資料庫處於 ARCHIVELOG 模式(“ARCHIVE LOG LIST”命令顯示 Archivelog模式)

擁有受影響檔案的完好備份。請注意,在某些情況下,壞塊可能已經存在,但在很長一段時間內未被發現。如果最近的資料檔案備份仍包含壞塊,那麼只要您擁有所有必需的歸檔日誌,就可以嘗試使用更早的備份。
(通常可以使用 DBV START= / END= 選項來檢查位於某個備份檔案的恢復副本中的特定塊是否損壞)

從備份時間開始到當前時間點的所有歸檔日誌均可用

當前的線上日誌均可用且完好無缺

錯誤不是由執行NOLOGGING 操作之後執行的恢復所導致的
如果滿足上述條件,完全恢復通常是首選方法
但請注意:
(a) 如果事務回滾已發現壞塊位於物件上,而非 rollback 段本身,則 undo 操作可能已被放棄。在這種情況下,可能需要在恢復完成後重建索引/檢查資料完整性。

(b) 如果要恢復的檔案包含自上次備份以來執行的 NOLOGGING 操作的資料,在使用了資料檔案或資料庫恢復的情況下,這些塊將被標記為“壞塊”。在某些情況下,這會使情況更加糟糕。

如果執行資料庫恢復後壞塊仍然存在,則表示所有備份都包含壞塊,底層錯誤仍存在,或問題透過redo 重現。在這些情況下,需要選擇其他一些恢復選項。

如果不需要從物件本身提取任何資料,能否刪除或重新建立該物件?
您可以刪除物件或從指令碼/最近匯出的副本重新建立物件。一旦刪除一個物件後,該物件中的塊將被標記為“空閒”,並且該塊在被分配到新物件時將被重新格式化.明智的做法是,對錶進行重新命名,而不是刪除,除非您完全確定不再需要其中的資料。

對於表分割槽,只需要刪除受影響的分割槽。例如:ALTER TABLE ...DROP PARTITION ...

如果壞塊影響到分割槽段頭,或者包含分割槽頭的檔案處於離線狀態,則 DROP PARTITION 可能會失敗。在這種情況下,首先將其更換為具有相同定義的表,之後仍然可以刪除該分割槽。
例如:ALTER TABLE ..EXCHANGE PARTITION ..WITH TABLE ..;
最常見的可重建物件為索引。始終在處理表中的索引問題之前處理表壞塊

對於任何段,如果您擁有壞塊的絕對檔案號和塊號,則可使用以下快速提取物件 DDL 的方法:
set long 64000
select dbms_metadata.get_ddl(segment_type, segment_name, owner)
FROM dba_extents
WHERE file_id=&AFN AND &BL BETWEEN block_id AND block_id + blocks -1;

是否需要在重新建立物件之前搶救資料?
如果問題位於定期更新的關鍵應用表上,則可能需要儘可能多地搶救表中資料,然後重新建立該表。

當前忽略壞塊是否可取?
在某些情況下,最直接的選項可能就是忽略壞塊,並阻止應用程式對它進行訪問。

最後的選項
將資料庫或表空間恢復到較早的時間點(透過時間點恢復)或還原出現壞塊前的冷備份或使用現有匯出檔案

完全恢復
如果資料庫處於ARCHIVELOG 模式下,且擁有受影響檔案的完好備份,則恢復通常為首選方法.這不保證可以解決問題,但的確可以有效的解決大部分壞塊問題.如果恢復再次引發問題,則返回到以上選項列表並選擇其他方法.

如果使用的是Oracle9i(或更高版本),則可以使用RMAN BLOCKRECOVER命令執行塊級恢復。

如果使用的是較早版本的Oracle,則可以執行資料檔案恢復(資料庫其他部分可以繼續執行),或資料庫恢復(需要關閉資料庫)

如果使用的是Oracle 11g(或更高版本,則可以使用“Data Recovery Advisor(資料恢復指導)”.

塊級恢復
自Oracle9i版本起,RMAN允許恢復單個塊,同時資料庫的其他部分(包括資料檔案中的其他塊)仍可以進行正常訪問.請注意,塊級恢復只能將塊完全恢復到當前時間點.要使用此選項恢復單個塊,不一定要使用 RMAN 進行備份.
例如:
實際情況是,檔案6的塊30上發生ORA-1578錯誤,可能是由於介質問題導致的壞塊,且您擁有該檔案的完好冷備份映像,並已還原到“.../RESTORE/filename.dbf”.假設所有歸檔日誌均存在(位於預設位置),則可以透過RMAN使用以下命令序列執行塊級恢復:
rman nocatalog
connect target
catalog datafilecopy '.../RESTORE/filename.dbf';
run {blockrecover datafile 6 block 30;};
此操作將使用註冊的資料檔案備份映像和任何需要的歸檔日誌來執行塊恢復,僅將有問題的塊恢復到當前時間點.

資料檔案恢復
資料檔案恢復包括下列步驟.如果有多個檔案,則針對每個檔案重複執行這些步驟,或參閱下面的“資料庫恢復”.當資料庫處於 OPEN 或 MOUNTED 狀態時,均可使用這些步驟.
使受影響的資料檔案離線
例如:ALTER DATABASE DATAFILE 'name_of_file' OFFLINE;

將檔案複製到安全位置(以防備份損壞)

將檔案的最新備份還原到完好的磁碟上

使用DBVERIFY檢查還原的檔案是否有壞塊

假設還原的檔案完好,則將資料檔案重新命名並儲存到新位置(如果不是原來的位置)
例如:ALTER DATABASE RENAME FILE 'old_name' TO 'new_name';

恢復資料檔案
例如:RECOVER DATAFILE 'name_of_file';

使資料檔案上線
例如:ALTER DATABASE DATAFILE 'name_of_file' ONLINE;

資料庫恢復
資料庫恢復通常包含以下步驟:
關閉資料庫(使用選項 immediate 或 abort)

將待恢復的所有檔案的當前副本複製到安全位置

將備份檔案還原到完好的磁碟上

請勿還原控制檔案或線上REDO 日誌檔案

使用DBVERIFY檢查還原的檔案

啟動資料庫到MOUNT狀態(startup mount)

對任何需要重新定位的資料檔案進行重新命名
例如:ALTER DATABASE RENAME FILE 'old_name' TO 'new_name';

確保所有必需的檔案線上
例如:ALTER DATABASE DATAFILE 'name_of_file' ONLINE;

恢復資料庫
例如:RECOVER DATABASE

開啟資料庫
例如:ALTER DATABASE OPEN;

一旦執行了完全恢復,最好在允許使用之前先檢查資料庫:
針對每個問題物件執行“ANALYZE <table_name> VALIDATE STRUCTURE CASCADE”,檢查表/索引是否存在不匹配。如果有任何 und 操作曾被放棄,此命令可能會顯示不匹配,此時需要重建索引。

在應用程式級別檢查表中資料的邏輯完整性。

重建索引
損壞物件為使用者索引時,如果底層表沒有損壞,則可以刪除並重建該索引。

如果底層表也已經損壞,則應在重建任何索引之前先解決該表的壞塊。

如果收集的資訊表示索引有從屬外來鍵約束,則需要執行以下操作:
ALTER TABLE <child_table> DISABLE CONSTRAINT <fk_constraint>;

使用以下命令重建主鍵
ALTER TABLE

DISABLE CONSTRAINT <pk_constraint>; DROP INDEX <index_name>; CREATE INDEX <index_name> .. with appropriate storage clause ALTER TABLEENABLE CONSTRAINT <pk_constraint>;

啟用外來鍵約束
ALTER TABLE <child_table> ENABLE CONSTRAINT <fk_constraint>;

對於索引分割槽,以執行以下命令:
ALTER INDEX ...REBUILD PARTITION ...;

注意:
(1) 不要使用“ALTER INDEX .. REBUILD”命令重建損壞的非分割槽索引,這一點非常重要,因為此操作通常會嘗試從包含壞塊的現有索引段中構建新索引..“ALTER TABLE ... REBUILD ONLINE”和“ALTER INDEX ... REBUILD PARTITION ...”不會從舊索引段中構建新索引,因此可以使用。

(2) 如果新索引包含的列為現有索引的子集,則 Create INDEX 可以使用現有索引中的資料,因此,如果您有兩個損壞的索引,應在重建之前將兩個都刪除。

(3) 重建索引時,請確保使用正確的儲存選項。

搶救表中資料
如果損壞的物件為TABLE 或 CLUSTER 或 LOBSEGMENT,則必須明白,壞塊內的資料已經丟失.部分資料可能可以從塊的HEX轉儲中,或從索引涵蓋的列中搶救回來.

由於可能需要從索引中搶救壞塊中的資料,因此最好不要刪除任何現有索引,直至所有需要的資料提取完成。

從包含壞塊的表中提取資料有多種方法。選擇最恰當的方法,詳細資訊如下所述.這些方法的目的是從可訪問的表塊中提取儘可能多的資料.通常,將損壞的表重新命名是一個比較好的方法,這樣就可以使用正確的名稱建立新物件.
例如:RENAME TO <emp_corrupt>;

從壞塊表中提取壞塊周圍資料的方法
(1) 從Oracle 7.2開始(包括 Oracle 8.0、8.1 和 9i)可以跳過表中的壞塊。
這是到目前為止最簡單的提取表資料的方法,用DBMS_REPAIR.SKIP_CORRUPT_BLOCKS or Event 10231

如果壞塊位於IOT overflow 段,則應使用相同的方法,不同的是使用Event 10233和全索引掃描

請注意,此方法只適用於塊的“包裝”已被標記為“壞塊”的情況。例如:如果塊報告 ORA-1578 錯誤。如果問題為 ORA-600 或其他非ORA-1578 錯誤,則通常可以使用 DBMS_REPAIR 將表中壞塊標記為“軟壞塊”。這樣在您訪問該資料塊時,系統將顯示 ORA-1578錯誤,從而可以使用 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS。

注意:被“FIX_CORRUPT_BLOCKS”程式標記為“壞塊”的塊在任何還原/恢復操作之後還將被標記為“壞塊”.

使用DBMS_REPAIR進行此操作概括起來步驟如下:
使用DBMS_REPAIR.ADMIN_TABLES 建立管理表

使用DBMS_REPAIR.CHECK_OBJECT 找到問題塊

在損壞問題塊之前將其中所有完好的資料匯出。

使用DBMS_REPAIR.FIX_CORRUPT_BLOCKS將找到的問題塊標記為“壞塊”,然後它們就會顯示 ORA-1578

如果需要,使用 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS跳過表中的壞塊。

(2) 從 Oracle 7.1 開始,可以使用 ROWID 範圍掃描.此功能的語法較為複雜,但可以使用 ROWID提示選擇壞塊周圍的資料.

(3) 如果存在主鍵,則可以透過此索引選擇表資料。也可以透過任何其他索引選擇一些資料。此方法較慢,花費時間較長,通常只有 Oracle 7.0 版本才使用

(4) 有多種搶救程式/PLSQL 指令碼可用於搶救表中的資料。與上述方法相比,這些方法在設定和使用方面需要花費更長的時間,但常常能夠處理除 ORA-1578 之外的各類壞塊

從包含損壞的LOBSEGMENT 塊的表中提取資料的方法:
在 LOB 段上不可以使用 DBMS_REPAIR,如果壞塊 LOB 塊未被表中的任何行引用,則應該可以使用 CREATE TABLE as SELECT (CTAS)來按選擇建立表,或按原樣匯出/刪除/匯入該表。

如果壞塊LOB 塊被某個行引用,則應該可以使用不包括問題行的WHERE謂詞進行選擇或匯出

注意:可以將問題行的LOB列值更新為NULL,從而使SELECT操作不再返回ORA-1578錯誤,但是壞塊將等待被重新使用,隨著對行中的 LOB列進行INSERT或UPDATE操作,當有問題的塊被重新使用時,最後還是會報ORA-1578錯誤,那時的情況比已知行出現壞塊更糟糕.因此,只有您打算立刻重新建立表,才應該將LOB列設為NULL.

從壞塊本身提取資料
由於壞塊本身已經“損壞”,則從該塊中提取的任何資料都應被視為可疑資料,從壞塊本身獲取資料行的主要方法包括:
對於 TABLE 的塊,Oracle Support 可以使用一款嘗試解釋塊內容的工具。

使用表中現有索引,利用落在壞塊內的ROWID 來提取索引所涵蓋的列資料,上文提到的 ROWID 範圍掃描文章在接近結束時對此內容有所介紹:
對於 Oracle8/8i,請參閱 Document 61685.1
對於 Oracle7,請參閱 Document 34371.1

在 redo 流上可以使用 LogMiner 來查詢向問題塊載入資料的初始插入/更新操作。此處的主要因素是資料實際被放入問題塊的時間.例如,行2可能在昨天已插入,而行1可能在1年前已插入.

忽略壞塊
出錯時可以忽略壞塊並接受報告的錯誤,或在應用程式級別阻止對出問題的塊行進行訪問。
例如:如果問題塊/行位於子表中,則可以在應用程式級別阻止對父表中對應行的訪問,從而子行就永不會被訪問(但要注意級聯類約束)

這樣做可能不利於批次訪問資料的報告和其他任務,因此,為了阻止塊在被訪問時報錯,前面所述的DBMS_REPAIR選項也不失為一個可取的方法.使用這種方法標記並跳過壞塊提供了一種短期的解決方案.從而在計劃停機時可以嘗試進行完全資料搶救和/或恢復,或留出更多時間在第二個(克隆)資料庫上嘗試其他恢復選項.但請注意,使用DBMS_REPAIR.FIX_CORRUPT_BLOCKS標記塊壞塊將導致標記的塊在恢復後還是“壞塊”。

忽略壞塊對於快速老化且即將被清除的資料而言是比較好的選擇(例如,在按日期分割槽的表中,較老的分割槽將在某時間點被刪除).

忽略LOB段上的壞塊
在應用程式級別,可以忽略損壞的LOB列,直到可以重新構建該表.確保不出現上述“警告”中的情形的一種方法是確保應用程式只能透過表上的包含WHERE 謂詞的檢視來訪分表中的資料.
例如:假設表 MYTAB(a number primary key,b clob)有一行或多行指向損壞的 LOB 資料。
ALTER TABLE MYTAB ADD ( BAD VARCHAR2(1) );

CREATE VIEW MYVIEW AS SELECT a,b FROM MYTAB WHERE BAD is null;

對任何問題行設定 BAD='Y'

如果只通 MYVIEW 訪問 MYTAB,該行將永不可見,因此也無法更新,從而實現了壞塊條目隔離,直到問題解決.

很明顯,此示例更多的是一個設計時解決方案,但某些應用程式可能已有類似機制,且可能只透過某個檢視(或透過 RLS 策略)訪問資料,從而提供某些選項來隱藏問題行。

針對忽略壞塊的警告
雖然可以忽略壞塊,但需要注意的是,壞塊在執行DBVERIFY,RMAN 備份時仍然會以警告/錯誤等形式出現。請務必仔細記錄您將在這些工具中看到的任何壞塊,尤其是您期望在使用RMAN時跳過的任何塊(例如,設定了 MAX_CORRUPT),並確保在清除壞塊後移除任何對錯誤的“接受”選項.
例如:假設壞塊已處理為忽略壞塊,並在應用程式級別跳過問題行。RMAN可能被配置為在備份時接受壞塊。然後在稍後的表重組期間重新建立表。如果 RMAN 配置未及時更新以反映目前已無任何錯誤,則 RMAN 可能會忽略稍後出現的某些其他壞塊。

此外,還有重要的一點需要注意,忽略table段中的壞塊可能導致查詢返回不一致的結果。
例如:設定了 SKIP_CORRUPT 的表可能出現不同的結果,具體取決於是使用了了索引掃描還是表訪問,其他報告可能只是報錯.。

請注意,如果忽略壞塊但使用DBMS_REPAIR.FIX_CORRUPT_BLOCKS標記,系統會向壞塊中寫入redo資訊,這可能會限制後續的恢復選項.

最後的選項
如果你有standby環境(物理或邏輯),請首先對其進行檢查。

無論問題發生在何種型別的塊上,均可使用一種可能的選項,即將資料庫或問題表空間恢復到出現壞塊之前的某個時間點.此選項的困難之處在於,並不總能知道問題首次出現的時間.

DBVERIFY通常可用於檢查還原的檔案是否存在壞塊.尤其是,START= / END= DBV選項可用於在還原的備份映像上快速進行首次測試,以檢查問題塊本身是否出錯。

下面列出了一些可用於進行恢復操作的最終選項,當出現其中一種或多種情況:
您丟失了非常重要的資料檔案(或資料檔案出現壞塊),而沒有問題檔案的正常備份(無壞塊)
既不處於ARCHIVELOG 模式,也沒有自檔案建立以來的全部歸檔日誌
完全恢復後仍重複出現問題

最後的機會:
請注意,如果丟失了資料檔案的所有副本,但仍具有自檔案建立以來的全部歸檔日誌,則仍有可能恢復該檔案。
例如:
ALTER DATABASE CREATE DATAFILE '....'[as '...'] ;

RECOVER DATAFILE '....'

ALTER DATABASE DATAFILE '....'ONLINE;
如果您遇到這種情況,請在繼續下面的操作之前先嚐試使用這些步驟來恢復資料檔案。

如果您到達這一步,就說明沒有其他辦法可以將檔案恢復到當前時間點.此時最好關閉例項,並對當前資料庫進行備份,以便在選用的措施失敗後仍然能夠回退到當前時間點.(例如:如果發現備份壞塊).

可用的一些選項概述如下:
恢復到早期的冷備份
例如:如果處於 NOARCHIVELOG 模式
從冷備份建立克隆資料庫
並提取(匯出)問題表
或傳輸問題表空間

使用基於時間點的恢復將資料庫恢復到一致的時間點
需要完好備份和任何所需的歸檔日誌
必須還原所有檔案且將整個資料庫前滾到恰當的時間點。
可以在克隆資料庫中執行基於時間點的恢復,然後將問題表空間傳輸到問題資料庫,或將問題表利用匯出/匯入工具從克隆資料庫匯入到問題資料庫.

表空間基於時間點的恢復
可以僅對受影響的表空間執行基於時間點的恢復.

從邏輯匯出/副本重新建立資料庫
需要具有完好的資料庫邏輯備份
注意:要使用此選項,必須重新建立資料庫。
與其他選項一樣,可以在克隆資料庫中進行重新建立,只為獲得問題表的完好映像.

總之做好備份是DBA最重要的工作.


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

相關文章