處理 Oracle 塊損壞 (文件 ID 1526911.1)
適用於:
Oracle Database - Enterprise Edition - 版本 7.0.16.0 到 11.2.0.2.0 [發行版 7.0 到 11.2]本文件所含資訊適用於所有平臺
用途
處理 Oracle7/8/8i/9i/10g/11g/12c 中的 Oracle 塊損壞
詳細資訊
文件內容
由於 NOLOGGING 或 UNRECOVERABLE 操作導致的壞塊
Options for various Segment Types:
CACHE CLUSTER INDEX PARTITION INDEX LOBINDEX LOBSEGMENT ROLLBACK
TABLE PARTITION TABLE TEMPORARY IOT(索引組織表) TYPE2 UNDO 其他一些段型別 No Segment
塊級恢復 ,
資料檔案恢復 ,
資料庫恢復 ,
簡介
本文章討論如何處理 Oracle 資料檔案中的一個或多個壞塊,並介紹了處理這些壞塊的主要方法。在採取任何措施之前,請先閱讀完整篇文章。
本文件未介紹記憶體壞塊問題(通常為 ORA-600 [17xxx] 型別錯誤)。
注意: 如果在啟動時出現 ORA-1578 問題,請與當地支援中心聯絡,以獲得參考建議。
本文章介紹了許多型別的錯誤,很多其他地方也可能引用到本文章。重要的是,您需要知道關於每個壞塊的以下資訊:
-
包含壞塊的檔案的絕對檔案編號 (FILE NUMBER)。
本文中稱為“&AFN”。
-
包含壞塊的檔案的名稱。
本文中稱為“&FILENAME”。
如果您知道檔案編號,但不知道檔名,則可以使用 V$DATAFILE 來獲取檔名:
SELECT name FROM v$datafile WHERE file#=&AFN;如果檔案號未顯示在 Oracle8i 的 V$DATAFILE 中,且 &AFN 大於 DB_FILES 引數值,則該檔案可能是臨時檔案。在這種情況下,可以使用以下查詢找到檔名:
SELECT name FROM v$tempfile WHERE file#=(&AFN - &DB_FILES_value);
-
檔案中壞塊的塊編號。
本文中稱為“&BL”。
-
包含受影響塊的表空間編號和名稱。
本文中稱為“&TSN”(表空間編號)和“&TABLESPACE_NAME”。
如果您不知道這些資訊,請使用以下查詢找到它們:
SELECT ts# "TSN" FROM v$datafile WHERE file#=&AFN;
SELECT tablespace_name FROM dba_data_files WHERE file_id=&AFN; -
表空間中的壞塊大小。
本文中稱為“&TS_BLOCK_SIZE”。
SELECT block_size FROM dba_tablespaces
WHERE tablespace_name =
(SELECT tablespace_name FROM dba_data_files WHERE file_id=&AFN);
對於 Oracle 7、8.0 和 8.1,資料庫中所有表空間使用相同的塊大小。
對於這些版本,使用命令"SHOW PARAMETER DB_BLOCK_SIZE" 返回的值作為 “ &TS_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'
那麼:
&RFN 為 "7" (從錯誤 ORA-1578 的"file #"部分獲得)
&BL 為 "12698" (從錯誤 ORA-1578 的"block #"部分獲得)
&FILENAME 為 '/oracle1/oradata/V816/oradata/V816/users01.dbf'
&TSN 及其他資訊可以從上面提到的 SQL 語句獲得
對於其他錯誤(ORA-600、ORA-1498 等),上述值應由 Oracle Support 提供給您,或從涵蓋相關錯誤的文章中獲取。
對於某些錯誤,如 ORA-1410“invalid ROWID(無效 ROWID)”、ORA-12899“value too large for column(列值過大)”等,未給出損壞的檔案/塊的詳細資訊。對於此類情況, Note:869305.1 可以幫助您定位損壞的行。
概述處理壞塊的步驟
有多種原因可能導致壞塊,包括:
-
- 壞的 IO 硬體/韌體
- OS 問題
- Oracle 問題
-
對於執行過“UNRECOVERABLE”或“NOLOGGING”操作的資料庫進行恢復
(在這種情況下可能產生 ORA-1578 錯誤 - 如下方所示)
產生 Oracle 錯誤的時間點可能要比最初發生任何塊損壞的時間點晚得多。
在遇到壞塊時,我們通常無從瞭解根本原因,並且在大多數情況下,當下最迫切的需求是重新啟動資料庫並使其執行起來,正因如此,本文將介紹用於解決壞塊問題的步驟,如下所列:
-
確定壞塊問題的範圍,並確定這些問題是永續性問題還是暫時性問題。
如果問題涉及範圍很大,或錯誤不穩定,則關鍵在於先識別原因(檢查硬體等)。這點很重要,因為如果是底層硬體出現錯誤,恢復系統便毫無意義。
- 更換或拆下任何有問題的或可疑的硬體。
- 確定哪些資料庫物件受到影響。
- 選擇最合適的資料庫恢復/資料搶救選項。
對於上述所有步驟,最好應收集證據並詳細記錄所採取的措施。本文中的“證據>>”標籤列出了應收集的資訊,以幫助您識別問題的根本原因。
由於 NOLOGGING 或 UNRECOVERABLE 操作導致的壞塊
如果對某個物件執行了 NOLOGGING(或 UNRECOVERABLE)操作,隨後又恢復了包含該物件的資料檔案,則受到 NOLOGGING 操作影響的資料塊將被標記為“壞塊”,當您訪問該資料塊時將顯示 ORA-1578 錯誤。
從Oracle8i開始報錯ORA-26040("ORA-26040:
Data block was loaded using the NOLOGGING
option"),此時原因一目瞭然,而較早版本中則沒有附件這條錯誤訊息。如果壞塊是由於對執行過 NOLOGGING
操作的資料檔案進行恢復而產生的,則可以使用本文中從 Section 3 "Information to Record for Each Corruption" 開始之後介紹的內容,但請注意以下問題:
-
- 恢復操作無法找回受 NOLOGGING 操作影響的資料
- 塊內的資料無法搶救
- 解決方法請參考Note:794505.1
(1) 確定壞塊問題的範圍
請參考Note 836658.1查詢壞塊的範圍。使用 RMAN或者DBVERIFY 掃描受影響的檔案(以及一切重要的檔案)也是不錯的辦法,這樣可以檢查是否有其他壞塊,從而確定問題的範圍。有關使用 DBVERIFY 的詳細資訊,請參閱 Note:35512.1
每次發生壞塊錯誤時,都應記下完整的錯誤訊息,並檢視該例項的告警日誌和跟蹤檔案,以瞭解任何相關的錯誤。首先進行這些步驟非常重要,這可以評估該損壞是單個塊,還是由於 UNRECOVERABLE 操作產生的錯誤,抑或是更嚴重的問題。
一旦確定了損壞的檔案/塊組合列表,即可使用以下步驟來幫助確定應採取何種措施。
- 完整記錄初始錯誤,以及發生錯誤的應用程式的詳細資訊。
- 及時地儲存從告警日誌中首次 (FIRST) 記錄到問題前數小時到當前時間點所提取的內容。
- 儲存告警日誌中提到的任何跟蹤檔案。
- 記錄最近遇到的任何 OS 問題。
- 記錄是否正在使用任何特殊功能,例如:ASYNC IO、快速寫入磁碟選項等。
- 記錄當前的備份位置(日期、型別等)
-
記錄資料庫是否處於 ARCHIVELOG 模式,
例如:在SQL*Plus(或 Server Manager)中執行“ARCHIVE LOG LIST”
(2) 更換或拆下可疑硬體
大多數壞塊問題是由故障硬體導致的。
如果出現硬體錯誤或可疑元件,最好進行修復,或者在執行恢復操作之前,確保在單獨的磁碟子系統上有足夠的可用空間用於恢復。
您可以使用以下步驟移動資料檔案:
-
- 確保要遷移的檔案已離線或資料庫例項處於 MOUNT 狀態(未開啟)
-
將該資料檔案物理還原(或複製)到新位置
例如:/newlocation/myfile.dbf -
將該檔案的新位置告知 Oracle。
例如:ALTER DATABASE RENAME FILE '/oldlocation/myfile.dbf' TO '/newlocation/myfile.dbf';
(請注意,您不能對臨時檔案進行重新命名,而應刪除臨時檔案並在新位置重新建立)
或 受影響檔案所在的 OS 層面出現錯誤
或 錯誤是暫時性的且遊離不定,
那麼,如果不解決底層問題或準備另外的磁碟空間,那麼進行任何操作都是毫無意義的。
與硬體供應商聯絡,以全面檢查系統,並聯系 Oracle Support,告知所有錯誤詳情。
請注意: 如果硬體檢查失敗,即表明存在硬體問題,但硬體檢查成功透過卻並不能證明沒有硬體相關問題 — 硬體測試報告成功但確實存在底層錯誤,這種情況也是經常發生。
如果使用了任何特殊 IO 選項,例如 direct IO、async IO 或類似的選項,最好將其禁用,以消除這些選項成為潛在問題原因的可能性。
(3) 每次壞塊需記錄的資訊
在決定如何恢復之前,最好先確定哪些物件受到了影響,因為壞塊可能發生在那些容易被重新建立的物件中。
例如:對於只有 5 行資料的表中發生的壞塊,刪除並重新建立表可能要比執行恢復快得多。
對於每個壞塊,請收集下表中的資訊。
進行此操作的步驟如下所述。
針對每次壞塊需記錄的資訊 | ||||||||
---|---|---|---|---|---|---|---|---|
初始錯誤 |
絕對檔案號 &AFN |
相關檔案號 &RFN |
塊編號 &BL |
表空間 | 段型別 |
段 所有者.名稱 |
相關物件 | 恢復選項 |
下列說明將有助於您針對每個壞塊填寫此表。
- "初始錯誤"最初報告的錯誤。例如:ORA-1578/ORA-1110、ORA-600 和所有引數等。
-
"絕對檔案號", "相關檔案號"和"塊號"檔案號和塊號應該已在錯誤中顯示,或由 Oracle Support 提供,或在指引您參考本文章的其他文章的步驟中提供。
在 Oracle8/8i/9i/10g 中: 絕對檔案號和相關檔案號通常是一樣的,但也可能不同(尤其是在資料庫是由 Oracle7 遷移而來的情況下)。請務必獲得正確的 &AFN 和 &RFN 編號,否則您可能最終搶救的是錯誤的物件!!
ORA-1578 報告相關檔案號,絕對檔案號在伴隨的 ORA-1110 錯誤中顯示。對於 ORA-600 錯誤,您應該會被告知絕對檔案號。
下列查詢將顯示資料庫中資料檔案的絕對和相關檔案號:SELECT tablespace_name, file_id "AFN", relative_fno "RFN" FROM dba_data_files;[Insert code here. Use 'Paste from Word' to retain layout.]在 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”和塊編號“&B”的情況下,下列查詢將顯示物件的段型別、所有者和名稱,資料庫必須開啟才能使用此查詢:
SELECT * 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;
(4) Which Object is affected and 可能的恢復選項:
相關物件和能夠使用的恢復選項取決於 SEGMENT_TYPE。對於各種最常見的段型別,其他查詢和可能的恢復選項如下所列。
CACHE
CLUSTER
INDEX PARTITION
INDEX
LOBINDEX
LOBSEGMENT
ROLLBACK
TABLE PARTITION
TABLE
TEMPORARY
IOT
TYPE2 UNDO
Some other Segment Type
"no rows" from the query
CACHE
如果段型別為 CACHE,請再次檢查您是否輸入了正確的 SQL語句和引數。
解決方法:修復資料塊採用塊級恢復方法
{Continue} {Back to Segment List}
CLUSTER
如果段型別為 CLUSTER,則應確定它包含哪些表。
解決方法:
修復資料塊採用塊級恢復方法
{Collect TABLE information} {Back to Segment List}
INDEX PARTITION
如果段型別為 INDEX PARTITION,請記錄名稱和所有者,然後確定哪些分割槽受到影響:
FROM dba_extents
WHERE file_id = &AFN AND &BL BETWEEN block_id AND block_id + blocks - 1
解決方法:
或者
使用下列語句可以重建索引分割槽:
ALTER INDEX xxx REBUILD PARTITION ppp;
(請注意下方“重建索引”中所述的 REBUILD 選項)
{Continue} {Back to Segment List}
INDEX
確定索引位於哪個表中:
FROM dba_indexes
WHERE owner='&OWNER' AND index_name='&SEGMENT_NAME';
CONSTRAINT_TYPE 的可能值包括:
- P 索引支援主鍵約束。
- U 索引支援唯一約束。
如果索引支援主鍵約束(型別“P”),則確認主鍵是否被任何外來鍵約束引用:
FROM dba_constraints
WHERE r_owner='&TABLE_OWNER' AND r_constraint_name='&INDEX_NAME';
解決方法:
修復資料塊採用塊級恢復方法
或 重建索引(任何相關聯的約束會隨之禁用/啟用)
(請注意下方"重建索引"中所述的 REBUILD 選項)。如果物件owner是sys使用者,那麼請聯絡oracle技術支援。
{Continue} {Back to Segment List}
ROLLBACK
如果段型別為 ROLLBACK,請聯絡 Oracle Support,因為 ROLLBACK 段壞塊需要特殊處理。
解決方法:
修復資料塊採用塊級恢復方法
{Continue} {Back to Segment List}
TYPE2 UNDO
TYPE2 UNDO 是系統管理的 undo 段,它是 rollback 段的一種特殊形式。這些段的壞塊需要特殊處理。
解決方法:
修復資料塊採用塊級恢復方法
{Continue} {Back to Segment List}
TABLE PARTITION
如果段型別為 TABLE PARTITION,請記錄名稱和所有者,然後確定哪些分割槽受到影響:
FROM dba_extents
WHERE file_id = &AFN
AND &BL BETWEEN block_id AND block_id + blocks - 1;
然後按照處理 TABLE 段的步驟繼續下面的操作。
解決方法:
或者
如果所有壞塊均位於同一個分割槽,則此時可以採取的一個做法是用一個空表 EXCHANGE 壞塊所在的分割槽,這可以讓應用程式繼續執行(無法訪問壞塊所在的分割槽中的資料),然後可以從之前的空表中提取任何未損壞的資料。
有關其他選項,請參見下面的 TABLE 選項。
{Continue} {Back to Segment List}
TABLE
如果所有者為“SYS”,則聯絡 Oracle Support 並上傳所有詳細資訊。
可能需要恢復資料庫。
對於非字典 TABLE 或 TABLE PARTITION,確定表中存在哪些索引:
FROM dba_indexes
WHERE table_owner='&OWNER'
AND table_name='&SEGMENT_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”,則聯絡 Oracle Support 並上傳所有詳細資訊。
對於非字典表,可能的選項包括:
恢復
或 搶救表(或分割槽)中的資料
然後 重新建立表(或分割槽)
或 忽略壞塊
(例如:使用 DBMS_REPAIR 標記需要跳過的問題塊)
{Continue} {Back to Segment List}
IOT(索引組織表)
IOT 表中的壞塊應按照表或分割槽表中的處理方式來處理。
唯一的例外是如果 PK 損壞。
IOT 表的 PK 就是表本身,它不能被刪除和重新建立。
解決方法:
修復資料塊採用塊級恢復方法
或者
如果所有者為“SYS”,則聯絡 Oracle Support 並上傳所有詳細資訊。
對於非字典表,可能的選項包括:
恢復
或 搶救表(或分割槽)中的資料
然後 重新建立表(或分割槽)
或 忽略壞塊
(DBMS_REPAIR 不適用於 IOT)
{Continue} {Back to Segment List}
LOBINDEX
確定 LOB 屬於哪個表:
SELECT table_name, column_name
fROM dba_lobs
wHERE owner='&OWNER'
AND index_name='&SEGMENT_NAME';
不可以重建 LOB 索引,因此您必須將該問題作為受影響的表中 LOB 列上的壞塊來處理。
使用 ”TABLE“ 部分中的 SQL 語句獲取包含損壞的 LOB 索引的表的索引和約束資訊,然後返回此處。
解決方法:
或者
移動LOG 段
如果所有者為“SYS”,則聯絡 Oracle Support 並上傳所有詳細資訊。
{Continue} {Back to Segment List}
LOBSEGMENT
確定 LOB 屬於哪個表:
例如:
SELECT table_name, column_name
FROM dba_lobs
WHERE owner='&OWNER'
AND segment_name='&SEGMENT_NAME';
對於非字典表 ...
使用 ”TABLE“ 部分中的 SQL 語句獲取包含壞塊的 LOB 資料的表的索引和約束資訊,然後返回此處查詢具體受影響的行的詳細資訊。
要查詢引用損壞的 LOB 塊的具體行可能比較困難,因為報告的錯誤中不會顯示錶中的哪一行資料包含損壞的 LOB 資料。
Typically one can refer to application logs or any SQL_TRACE or 10046 trace of a session hitting the error (if available) or see if having
set in the session helps identify the current SQL/binds/row.
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;
/
another script more generic:
exec dbms_output.enable(100000);
declare
pag number;
len number;
c varchar2(10);
charpp number := 8132/2;
begin
for r in (select rowid rid, dbms_lob.getlength (<your_clob_column>) len
from <your_table_with_clcob_column>) loop
if r.len is not null then
for page in 0..r.len/charpp loop
begin
select dbms_lob.substr (<your_clob_column>, 1, 1+ (page * charpp))
into c
from <your_table_with_clcob_column>
where rowid = r.rid;
exception
when others then
dbms_output.put_line ('Error on rowid ' ||R.rid||' page '||page);
dbms_output.put_line (sqlerrm);
end;
end loop;
end if;
end loop;
end;
/
解決方法:
可能需要恢復資料庫,如果所有者為“SYS”,則聯絡 Oracle Support 並上傳所有詳細資訊。
對於非字典表,可能的選項包括:
恢復
或者用empty_clob/empty_blob更新lob列,避免在出現ORA-1578;這樣可以清理表裡面的lob列:
SQL> update &table_owner.&table_with_lob
set &lob_column = empty_blob()
where rowid in ('list the identified rowids from the table from the plsql above');
將損壞的lob設定為empty lob後,之前的資料塊還會放回這個lob的freelist。這些空間以後可能會被重用,
當這些資料塊再次被使用時,會出現ORA-1578 錯誤,因此在empty lob後,再將lob 段移動到新的段:
或 搶救表(及其 LOB 列)中的資料
然後 重新建立表
或 忽略壞塊
(不可以在 LOB 段上使用 DBMS_REPAIR)
{Continue} {Back to Segment List}
TEMPORARY
如果段型別為 TEMPORARY,則壞塊不會影響永久物件。檢查發生問題的表空間是否正在被用作 TEMPORARY 表空間:
解決方法:
通常情況下,不需要進行任何還原,但如果磁碟可能有問題,且表空間包含有用資料,則最好對資料庫中受影響的檔案進行恢復。
{Continue} {Back to Segment List}
其他一些段型別
如果返回的段型別未包含在上述型別中,則請聯絡 Oracle Support 並提供迄今為止收集的所有資訊,以獲得相關建議。
{Continue} {Back to Segment List}
“無返回行”
如果沒有包含壞塊的 extent,則首先再次檢查查詢中使用的引數。如果您確定檔案號和塊編號是正確的,且不屬於 DBA_EXTENTS 中的某個物件,則執行以下操作:
-
再次檢查相關檔案是否為臨時檔案。
請注意,臨時檔案的檔案號取決於資料庫初始化引數 DB_FILES,因此對該引數的任何更改都會改變錯誤中報告的絕對檔案號。 - DBA_EXTENTS 不包含本地管理表空間中用於本地空間管理的塊。
- 如果您在資料庫執行查詢語句的時間點與出錯的時間點不相同,那麼問題物件可能已經被刪除,因此針對 DBA_EXTENTS 的查詢可能不會顯示任何行。
- 如果您正在調查的錯誤由 DBVERIFY 報告,則 DBV 將檢查所有塊,而不管它們是否屬於某個物件。因此,壞塊可能存在於資料檔案中,但卻未被任何物件使用。
選項:
未使用的 Oracle 塊上的錯誤可以忽略,因為如果需要使用該塊,Oracle 會建立新的塊映像(格式化),因此,該塊上的任何問題將永不會被讀取。
如果您懷疑該塊可能是空間管理塊,則可以使用 DBMS_SPACE_ADMIN 包來幫助您進行檢查:
以上命令會將不一致寫入跟蹤檔案,但如果遇到致命的壞塊,它將報告如下錯誤:
{Continue} {Back to Segment List}
證據
對於每個壞塊,如果需要嘗試並確定實際壞塊原因,則收集如下物理證據也是一個比較好的方法:
-
壞塊及位於其任意一側的塊的作業系統 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 上:
DUMP/BLOCKS=(start:XXXX,end:YYYY)/out=dump.out &FILENAME
其中 XXXX=作業系統塊編號(512 位元組塊中)
要計算此值,用報告的塊編號乘以“&TS_BLOCK_SIZE/512”。 -
處於 ARCHIVELOG 模式時,複製出錯時間前後的歸檔日誌檔案的安全副本,最好包括報告錯誤前數小時的日誌檔案。並且,儲存問題資料檔案在出錯前的所有副本,因為之前的資料檔案映像以及 redo 記錄有助於找出錯誤原因。
(DBV 通常可用於檢查問題是否存在於檔案的備份副本中)。理想的情況是獲得沒有報告壞塊的資料檔案備份映像,以及從該時間點開始到首次報告壞塊時間之後不久的時段內的所有 redo 記錄。
-
獲得問題塊的 Oracle 轉儲:
ALTER SYSTEM DUMP DATAFILE '&FILENAME' BLOCK &BL;(DUMP將生成到 USER_DUMP_DEST 下的跟蹤檔案)。
{Continue} {Back to Segment List}
(5) 選擇恢復選項
現在,最佳的恢復選項取決於受影響的物件。前面第 (3) 部分中的說明應該已經重點介紹了針對每個受影響物件的主要可用選項。選擇的實際恢復方法可能包含以下一種或多種混合方法:
是否需要進行任何恢復操作?
表空間中,或位於不再屬於任何資料庫物件的塊中,則無需進行任何操作,儘管將問題表空間重定位到其他儲存裝置中可能較為明智。
請參閱警告
可以使用完全恢復嗎?
要選用完全恢復,必須滿足如下條件:
-
資料庫處於 ARCHIVELOG 模式
(“ARCHIVE LOG LIST”命令顯示 Archivelog 模式)
-
擁有受影響檔案的完好備份。請注意,在某些情況下,壞塊可能已經存在,但在很長一段時間內未被發現。如果最近的資料檔案備份仍包含壞塊,那麼只要您擁有所 有必需的歸檔日誌,就可以嘗試使用更早的備份。
(通常可以使用 DBV START= / END= 選項來檢查位於某個備份檔案的恢復副本中的特定塊是否損壞) -
從備份時間開始到當前時間點的所有歸檔日誌均可用
-
當前的線上日誌均可用且完好無缺
-
錯誤不是由執行 NOLOGGING 操作之後執行的恢復所導致的
如果滿足上述條件,完全恢復通常是首選方法
*但請注意*
-
如果事務回滾已發現壞塊位於物件上,而非 rollback 段本身,則 undo 操作可能已被放棄。在這種情況下,可能需要在恢復完成後重建索引/檢查資料完整性。
-
如果要恢復的檔案包含自上次備份以來執行的 NOLOGGING 操作的資料,在使用了資料檔案或資料庫恢復的情況下,這些塊將被標記為“壞塊”。在某些情況下,這會使情況更加糟糕。
如果執行資料庫恢復後壞塊仍然存在,則表示所有備份都包含壞塊,底層錯誤仍存在,或問題透過 redo 重現。在這些情況下,需要選擇其他一些恢復選項。
請參閱 "(4A) 完全恢復" ,以瞭解完全恢復步驟。
如果不需要從物件本身提取任何資料,能否刪除或重新建立該物件?
您可以刪除物件或從指令碼/最近匯出的副本重新建立物件。一旦刪除一個物件後,該物件中的塊將被標記為“空閒”,並且該塊在被分配到新物件時將被重新格式化。明智的做法是,對錶進行重新命名,而不是刪除,除非您完全確定不再需要其中的資料。
對於表分割槽,只需要刪除受影響的分割槽。
如果壞塊影響到分割槽段頭,或者包含分割槽頭的檔案處於離線狀態,則 DROP PARTITION 可能會失敗。在這種情況下,首先將其更換為具有相同定義的表,之後仍然可以刪除該分割槽。
最常見的可重建物件為索引。始終在處理表中的索引問題之前處理表壞塊。
有關詳細資訊,請參閱"(4B) 重建索引" 。
對於任何段,如果您擁有壞塊的絕對檔案號和塊號,則可使用以下快速提取物件 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;
是否需要在重新建立物件之前搶救資料?
如果問題位於定期更新的關鍵應用表上,則可能需要儘可能多地搶救表中資料,然後重新建立該表。
有關詳細資訊,請參閱"" 。
當前忽略壞塊是否可取?
在某些情況下,最直接的選項可能就是忽略壞塊,並阻止應用程式對它進行訪問。
有關詳細資訊,請參閱 ""。
最後的選項
下列選項是否可行?
將資料庫或表空間恢復到較早的時間點(透過時間點恢復)
或還原出現壞塊前的冷備份
或使用現有匯出檔案
有關詳細資訊,請參閱""。
(5A) 完全恢復
如果資料庫處於 ARCHIVELOG 模式下,且您擁有受影響檔案的完好備份,則恢復通常為首選方法。
這不保證可以解決問題,但的確可以有效的解決大部分壞塊問題。如果恢復再次引發問題,則返回到以上選項列表並選擇其他方法。
如果使用的是 Oracle9i(或更高版本),則可以使用 RMAN BLOCKRECOVER 命令執行塊級恢復。
如果使用的是較早版本的 Oracle,則可以執行資料檔案恢復(資料庫其他部分可以繼續執行),或資料庫恢復(需要關閉資料庫)。
如果使用的是 Oracle 11g(或更高版本),則可以使用“Data Recovery Advisor(資料恢復指導)”.
塊級恢復
自 Oracle9i 版本起,RMAN 允許恢復單個塊,同時資料庫的其他部分(包括資料檔案中的其他塊)仍可以進行正常訪問。請注意,塊級恢復只能將塊完全恢復到當前時間點。
例如:
實際情況是,檔案 6 的塊 30 上發生 ORA-1578 錯誤,可能是由於介質問題導致的壞塊,且您擁有該檔案的完好冷備份映像,並已還原到“.../RESTORE/filename.dbf”。
假設所有歸檔日誌均存在(位於預設位置),則可以透過 RMAN 使用以下命令序列執行塊級恢復:
rman nocatalog
connect target
catalog datafilecopy '.../RESTORE/filename.dbf';
run {blockrecover datafile 6 block 30;}
此操作將使用註冊的資料檔案備份映像和任何需要的歸檔日誌來執行塊恢復,僅將有問題的塊恢復到當前時間點。
有關 RMAN BLOCKRECOVER 命令和限制的所有詳細資訊,請參閱文件 Note 144911.1。
資料檔案恢復
資料檔案恢復包括下列步驟。如果有多個檔案,則針對每個檔案重複執行這些步驟,或參閱下面的“資料庫恢復”。當資料庫處於 OPEN 或 MOUNTED 狀態時,均可使用這些步驟。
使受影響的資料檔案離線
將檔案複製到安全位置(以防備份損壞)
將檔案的最新備份還原到完好的磁碟上
使用 DBVERIFY 檢查還原的檔案是否有壞塊
有關使用 DBVERIFY 的詳細資訊,請參閱 Note:35512.1
假設還原的檔案完好,則將資料檔案重新命名並儲存到新位置(如果不是原來的位置)
恢復資料檔案
使資料檔案上線
資料庫恢復
資料庫恢復通常包含以下步驟:
將待恢復的所有檔案的當前副本複製到安全位置
將備份檔案還原到完好的磁碟上
請勿還原控制檔案或線上 REDO 日誌檔案
使用 DBVERIFY 檢查還原的檔案。有關使用 DBVERIFY 的詳細資訊,請參閱 Note:35512.1
對任何需要重新定位的資料檔案進行重新命名
確保所有必需的檔案線上
恢復資料庫
開啟資料庫
例如: ALTER DATABASE OPEN;
完全恢復後
一旦執行了完全恢復,最好在允許使用之前先檢查資料庫:
針對每個問題物件執行:
檢查表/索引是否存在不匹配。
如果有任何 undo 操作曾被放棄,此命令可能會顯示不匹配,此時需要重建索引。
在應用程式級別檢查表中資料的邏輯完整性。
(5B) 重建索引
損壞物件為使用者索引時,如果底層表沒有損壞,則可以刪除並重建該索引。
如果底層表也已經損壞,則應在重建任何索引之前先解決該表的壞塊。
如果收集的資訊表示索引有從屬外來鍵約束,則需要執行以下操作:
-
對於每個外來鍵
ALTER TABLE <table> DISABLE CONSTRAINT <pk_constraint>; -
使用以下命令重建主鍵
ALTER TABLE <table> DISABLE CONSTRAINT <pk_constraint>;
DROP INDEX <index_name>;
CREATE INDEX <index_name> .. with appropriate storage clause
ALTER TABLE <table> ENABLE CONSTRAINT <pk_constraint>; -
啟用外來鍵約束
ALTER TABLE <child_table> ENABLE CONSTRAINT <fk_constraint>;
對於索引分割槽,可以執行以下命令:
注意:
-
不要使用“ALTER INDEX .. REBUILD”命令重建損壞的非分割槽索引,這一點非常重要,因為此操作通常會嘗試從包含壞塊的現有索引段中構建新索引。
"ALTER INDEX ... REBUILD ONLINE" and "ALTER INDEX ... REBUILD PARTITION ..."
不會從舊索引段中構建新索引,因此可以使用。 - 如果新索引包含的列為現有索引的子集,則 Create INDEX 可以使用現有索引中的資料。因此,如果您有兩個損壞的索引,應在重建之前將兩個都刪除。
- 重建索引時,請確保使用正確的儲存選項。
(4C) 搶救表中資料
如果損壞的物件為 TABLE 或 CLUSTER 或 LOBSEGMENT,則您必須明白,壞塊內的資料已經丟失。
部分資料可能可以從塊的 HEX 轉儲中,或從索引涵蓋的列中搶救回來。
由於可能需要從索引中搶救壞塊中的資料,因此最好不要刪除任何現有索引,直至所有需要的資料提取完成。
從包含壞塊的表中提取資料有多種方法。選擇最恰當的方法,詳細資訊如下所述。這些方法的目的是從可訪問的表塊中提取儘可能多的資料。通常,將損壞的表重新命名是一個比較好的方法,這樣就可以使用正確的名稱建立新物件。
從壞塊表中提取壞塊周圍資料的方法
-
從 Oracle 7.2 開始(包括 Oracle 8.0、8.1 和 9i),可以跳過表中的壞塊。
這是到目前為止最簡單的提取表資料的方法,此方法在以下文件中做了討論:
Extracting data using DBMS_REPAIR.SKIP_CORRUPT_BLOCKS or Event 10231 Note:33405.1
如果壞塊位於 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 跳過表中的壞塊。 -
從 Oracle 7.1 開始,可以使用 ROWID 範圍掃描。
此功能的語法較為複雜,但可以使用 ROWID 提示選擇壞塊周圍的資料。
由於 Oracle7 和 Oracle8 中的 ROWID 格式有所不同,故有兩篇文章分別介紹此功能:
Using ROWID Range Scans to extract data in Oracle8 and higher Note:61685.1
Using ROWID Range Scans to extract data in Oracle7 Note:34371.1
-
如果存在主鍵,則可以透過此索引選擇表資料。
也可以透過任何其他索引選擇一些資料。
此方法較慢,花費時間較長,通常只有 Oracle 7.0 版本才使用。此方法在 Note:34371.1 中進行了介紹(此外,還介紹了 ROWID 範圍掃描)。 -
有多種搶救程式/PLSQL 指令碼可用於搶救表中的資料。與上述方法相比,這些方法在設定和使用方面需要花費更長的時間,但常常能夠處理除 ORA-1578 之外的各類壞塊。
由於這些方法通常需要由技術支援人員給予大量的親身指導,因此客戶可能看不到關於這些方法的部分文章。
要使用以下程式,需要使用 Pro*C,且需要了解如何構建 Pro*C 可執行檔案:
SALVAGE.PC for Oracle8.1 Note:97357.1
SALVAGE.PC for Oracle7 Note:2077307.6
要使用以下程式,需要手動互動:
SALVAGE.SQL for Oracle7/8 Note:2064553.4
SALVAGE.SQL for Oracle7/8 Note:28308.1
The following is only possible in Oracle8i and 9i. The aim is to mark the block as corrupt and then use the SKIP_CORRUPT table attribute to extract the table data:
Use DBMS_REPAIR to mark the block corrupt Note:68013.1
For corruption in a LONG column: Recreating a Table with a corruption in a LONG Note:876493.1
從包含損壞的 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 可以使用一款嘗試解釋塊內容的工具。
"Convert HEX or BLOCKDUMP to Readable form" Note:47419.1 -
使用表中現有索引,利用落在壞塊內的ROWID 來提取索引所涵蓋的列資料,上文提到的 ROWID 範圍掃描文章在接近結束時對此內容有所介紹:
對於 Oracle8/8i,請參閱 Note:61685.1
對於 Oracle7,請參閱 Note:34371.1 -
在 redo 流上可以使用 LogMiner 來查詢向問題塊載入資料的初始插入/更新操作。此處的主要因素是資料實際被放入問題塊的時間。
例如,行 2 可能在昨天已插入,而行 1 可能在 5 年前已插入。
(5D) 忽略壞塊
出錯時可以忽略壞塊並接受報告的錯誤,或在應用程式級別阻止對出問題的塊行進行訪問。
例如:如果問題塊/行位於子表中,則可以在應用程式級別阻止對父表中對應行的訪問,從而子行就永不會被訪問。(但要注意級聯類約束)
這樣做可能不利於批次訪問資料的報告和其他任務,因此,為了阻止塊在被訪問時報錯,前面
4C 中所述的 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 資訊,這可能會限制後續的恢復選項。
(5E) 最後的選項
如果你有 standby 環境(物理或邏輯),請首先對其進行檢查。
無論問題發生在何種型別的塊上,均可使用一種可能的選項,即將資料庫或問題表空間恢復到出現壞塊之前的某個時間點。此選項的困難之處在於,並不總能知道問題首次出現的時間。
DBVERIFY 通常可用於檢查還原的檔案是否存在壞塊。
有關使用 DBVERIFY 的詳細資訊,請參閱Note:35512.1 。尤其是,START= / END= DBV 選項可用於在還原的備份映像上快速進行首次測試,以檢查問題塊本身是否出錯。
本部分列出了一些可用於進行恢復操作的最終選項。
如果您看到這裡,則必定發生了以下一種或多種情況:
- 您丟失了非常重要的資料檔案(或資料檔案出現壞塊),而沒有問題檔案的正常備份(無壞塊)
- 既不處於 ARCHIVELOG 模式,也沒有自檔案建立以來的全部歸檔日誌
- 完全恢復後仍重複出現問題
最後的機會:
請注意,如果您丟失了資料檔案的所有副本,但仍具有自檔案建立以來的全部歸檔日誌,則仍有可能恢復該檔案。
例如:
ALTER DATABASE CREATE DATAFILE '....' [as '...'] ;
RECOVER DATAFILE '....'
ALTER DATABASE DATAFILE '....' ONLINE;
如果您遇到這種情況,請在繼續下面的操作之前先嚐試使用這些步驟來恢復資料檔案。
如果您到達這一步,就說明沒有其他辦法可以將檔案恢復到當前時間點。此時最好關閉例項,並對當前資料庫進行備份,以便在選用的措施失敗後仍然能夠回退到當前時間點。(例如:如果發現備份壞塊)。
可用的一些選項概述如下:
恢復到早期的冷備份
- 例如:如果處於 NOARCHIVELOG 模式
從冷備份建立克隆資料庫,並提取(匯出)問題表,或傳輸問題表空間。
使用基於時間點的恢復將資料庫恢復到一致的時間點
- 需要完好備份和任何所需的歸檔日誌
- 必須還原所有檔案且將整個資料庫前滾到恰當的時間點。
- 可以在克隆資料庫中執行基於時間點的恢復,然後將問題表空間傳輸到問題資料庫,或將問題表利用匯出/匯入工具從克隆資料庫匯入到問題資料庫。
表空間基於時間點的恢復
- 可以僅對受影響的表空間執行基於時間點的恢復。許多文件均對錶空間基於時間點的恢復做了介紹,如 Note:223543.1.
從邏輯匯出/副本重新建立資料庫
- 需要具有完好的資料庫邏輯備份
- 注意:要使用此選項,必須重新建立資料庫。
- 與其他選項一樣,可以在克隆資料庫中進行重新建立,只為獲得問題表的完好映像。
如果已具有完好備份,使用 DB_BLOCK_CHECKING=TRUE 進行前滾將有助於找到首次出錯的時間點。在調查恢復選項時,通常不需要關閉問題資料庫。
自 Oracle9i 起,您還可以使用“試驗恢復”選項來讓自己擺脫一邊研究選項一邊必須不斷還原備份的情形。
參考
NOTE:1543698.2 - Troubleshooting Assistant: Get Assistance to understand and solve Oracle Database Server CorruptionsNOTE:1088018.1 - Master Note for Handling Oracle Database Corruption Issues
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31393455/viewspace-2130466/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 處理塊損壞
- 第7章 處理塊損壞
- Oracle壞塊處理Oracle
- ORACLE 壞塊處理Oracle
- Oracle壞塊處理相關Oracle
- Oracle壞塊問題處理Oracle
- oracle corrupt block壞塊處理OracleBloC
- oracle10g rac 表決盤損壞、ocr損壞處理Oracle
- oracle - redo 損壞或刪除處理方法Oracle
- ORA-01578(資料塊損壞)跳過壞塊處理辦法
- 【BLOCK】Oracle壞塊處理命令參考BloCOracle
- oracle壞塊模擬處理(筆記)Oracle筆記
- Oracle 壞塊處理三板斧Oracle
- Oracle壞塊修復處理實驗Oracle
- rootvg壞塊處理
- (轉)oracle redolog損壞的處理辦法Oracle Redo
- ORACLE資料庫壞塊的處理 (處理無物件壞快的方法)Oracle資料庫物件
- 段頭損壞的處理
- Oracle資料庫塊的物理損壞與邏輯損壞Oracle資料庫
- ORACLE資料庫壞塊的處理 (一次壞快處理過程)Oracle資料庫
- 對oracle中出現的壞塊的處理方法Oracle
- ORACLE壞塊(ORA-01578)處理方法Oracle
- ORACLE中修復資料塊損壞Oracle
- DBA實踐---壞塊處理
- 資料庫壞塊處理資料庫
- 資料塊損壞ORA-1578(發現損壞塊)
- RAC磁碟頭損壞問題處理
- UNDO表空間損壞的處理
- 一次ORACLE資料庫undo壞塊處理Oracle資料庫
- ORACLE壞塊(ORA-01578)處理方法(zt)Oracle
- 教你如何處理Oracle資料庫中的壞塊Oracle資料庫
- Oracle 無備份情況下undo檔案損壞處理Oracle
- 【Oracle】Current online Redo 和 Undo 損壞的處理方法Oracle
- Oracle塊損壞恢復(有rman備份)Oracle
- BAD Block 壞塊的處理BloC
- 處理 Oracle7/8/8i/9i/10g/11g 中的 Oracle 塊損壞Oracle
- Oracle RMAN備份中對壞塊(corrupt block)的處理OracleBloC
- ORACLE-00600 4194 斷電undo損壞處理過程Oracle