您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何處理oracle中出現的壞塊”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“如何處理oracle中出現的壞塊”這篇文章吧。
在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最重要的工作.
以上是“如何處理oracle中出現的壞塊”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。