共計(jì) 5416 個(gè)字符,預(yù)計(jì)需要花費(fèi) 14 分鐘才能閱讀完成。
oracle 數(shù)據(jù)庫中如何格式化不屬于任何段的損壞塊,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
一、問題癥狀:
1. Rman 備份失敗,顯示 ORA-19566 錯(cuò)誤,且被報(bào)告的壞塊不屬于任何對象
2. Dbverify 顯示存在壞塊
3. 壞塊不屬于任何對象
二、原因分析:
在重新使用和重新格式化壞塊之前,RMAN 和 DBV 仍會(huì)一直報(bào)告壞塊。
三、解決方案:
解決此類問題的一個(gè)可能的方法如下。請注意,它不能保證問題解決,但它已知解決了幾種案例的問題。如果在某個(gè)數(shù)據(jù)文件中報(bào)告有很多塊損壞,請?jiān)诘诹教崾据斎? blocknumber 中輸入已經(jīng)報(bào)告的 *** 的壞塊號碼。
當(dāng)一個(gè)對象被重新創(chuàng)建,已經(jīng)分配給它 (甚至是損壞的塊) 的塊將變成空閑空間(free space)。他們在那里等待重新分配到一個(gè)需要額外空間的對象。一旦它們被重新分配到用于一個(gè)對象上新的 extent,只有當(dāng)任何 DML 操作使用到這些塊(即使損壞的塊,處在空閑空間,現(xiàn)在需要被分配),他們將在 DML 操作更改、使用這些塊之前,被重新格式化掉。
需要注意的是 extent 的簡單的分配不格式化塊。第 7 步分配的 extent 和第 8 步執(zhí)行 DML 操作,使用在第七步中分配的塊,這樣的壞塊才被重用和格式化。
在本文檔中,我們嘗試手動(dòng)重新格式化壞塊。
第 1 步 – 確定損壞的數(shù)據(jù)文件
損壞可以被報(bào)告在應(yīng)用層,如 DBV 和 RMAN,或 alert.log。
例如,可以在您的 RMAN 備份過程中獲得以下信息:
RMAN-03009: failure of backup command on nm4501 channel at 04/29/2005 09:44:41
ORA-19566: exceeded limit of 0 corrupt blocks for file E:\xxxx\test.ORA.
壞塊位于文件 E:\xxxx\test.ORA 中。
第 2 步 – 在受影響的數(shù)據(jù)文件上運(yùn)行 DBV/Rman 驗(yàn)證并檢查壞塊
在報(bào)告壞塊的數(shù)據(jù)文件上運(yùn)行 dbverify。
# dbv userid={system/password} file={full path filename} logfile={output filename}
第 3 步 – 檢查塊是否是某個(gè)對象的一部分 – 適用于損壞的塊號小的情況
查詢 dba_extents,確認(rèn)壞塊是否屬于任何對象。
SQL select segment_name, segment_type, owner from dba_extents where file_id = Absolute file number and corrupted block number between block_id and block_id + blocks -1;
如果塊不屬于任何對象,查詢 dba_free_space 確認(rèn)壞塊是否屬于數(shù)據(jù)文件的可用空間。
SQL Select * from dba_free_space where file_id= Absolute file number and corrupted block number between block_id and block_id + blocks -1;
第 4 步 – 查找受影響的塊并驗(yàn)證其是否屬于任何段的一種比較好的方法是使用 RMAN,這種方法既好用又便捷。
如果在第 2 步中已經(jīng)運(yùn)行了 rman 驗(yàn)證,請直接轉(zhuǎn)到下面給出的 sqlplus 腳本,以確認(rèn)對象。
$ rman target / nocatalog or $ rman target sys/ nocatalog run { allocate channel d1 type disk; allocate channel d2 type disk; ---------------------------------------------------------------------- -- multiple channels may be allocated for parallelizing purposes -- depends: RMAN - Min ( MAXOPENFILES , FILESPERSET ) -- Defaults: MAXOPENFILES =8, FILESPERSET =64 ---------------------------------------------------------------------- allocate channel dn type disk; backup check logical validate database;
注意:如果 RDBMS 是小于 11g 并且處于非歸檔模式下,則數(shù)據(jù)庫必須處于 mounted 模式
*** 在進(jìn)行進(jìn)一步操作之前,* 必須 * 運(yùn)行并完成 RMAN 命令“backup check logical validate database”。
*** 此命令完成 (基于文件) 后將會(huì)填充“v$database_block_corruption”視圖。
*** 如果未完成,在接下來的步驟中您就有可能得到無效 / 不完整的信息。
第 5 步 – 以非 SYS 或 SYSTEM(用戶)的用戶身份創(chuàng)建一個(gè)虛擬表
SQL connect scott/password
在包含出現(xiàn)壞塊的數(shù)據(jù)文件的表空間中創(chuàng)建虛擬表,并使用 nologging 選項(xiàng),以防止生成 redo 記錄:
SQL create table s ( n number, c varchar2(4000) ) nologging tablespace tablespace name having the corrupt block ;
不同的存儲(chǔ)參數(shù)可以被用來適應(yīng)特定的環(huán)境。
我們使用 PCTFREE 99 以加快該塊的格式化
確認(rèn)表是被創(chuàng)建在正確的表空間中,通過查詢 user_segments:
QL select segment_name,tablespace_name from user_segments where segment_name= S ;
請注意,在 11gR2 中,由于延遲段創(chuàng)建概念,從上面提到的 user_segments 查詢可能不會(huì)報(bào)告。在這種情況下,查詢 USER_TABLES
SQL select segment_name,tablespace_name from user_tables where segment_name= S ;
第 6 步 – 在虛擬表上創(chuàng)建觸發(fā)器,一旦重新使用壞塊,該觸發(fā)器便會(huì)引發(fā)異常
以 sysdba 身份連接,并創(chuàng)建以下觸發(fā)器:
請注意,在出現(xiàn)文件號提示時(shí),輸入相關(guān)文件號(v$datafile 中的 rfile# 值)
CREATE OR REPLACE TRIGGER corrupt_trigger AFTER INSERT ON scott.s REFERENCING OLD AS p_old NEW AS new_p FOR EACH ROW DECLARE corrupt EXCEPTION; BEGIN IF (dbms_rowid.rowid_block_number(:new_p.rowid)= blocknumber) and (dbms_rowid.rowid_relative_fno(:new_p.rowid)= filenumber) THEN RAISE corrupt; END IF; EXCEPTION WHEN corrupt THEN RAISE_APPLICATION_ERROR(-20000, Corrupt block has been formatted END; /
出現(xiàn)塊編號提示時(shí),輸入壞塊的塊編號。
出現(xiàn)文件號提示時(shí),輸入損壞的數(shù)據(jù)文件的相關(guān)文件號(v$datafile 中的 rfile# 值)。
第 7 步 – 為受影響的數(shù)據(jù)文件中的表分配空間。
請注意:
1)如果這是一個(gè) ASSM 表空間,你可能需要重復(fù)此步驟數(shù)次。也就是說,創(chuàng)建多個(gè)表和分配多個(gè) extent。
并周期性地查看 dba_extents,以確保空閑空間現(xiàn)在分配給一個(gè)虛擬表。
這是因?yàn)?ASSM 將自動(dòng)確定下一個(gè) extent 的大小
2)建議確保數(shù)據(jù)文件 AUTOEXTEND 置為 OFF,以防止其增長。
首先通過查詢 dba_free_space 查找 extent 大小
SQL Select BYTES from dba_free_space where file_id= file no and corrupt block no between block_id and block_id + blocks -1; BYTES ---------------- ---------- ---------- ---------- ---------- ------------ 65536
在本例中,它的大小是 64K。因此,按照以下方法分配 extent:
SQL alter table scott.s allocate extent (DATAFILE E:\xxxx\test.ORA SIZE 64K);
如果在這個(gè)數(shù)據(jù)文件中有多個(gè) 64K 的空閑 extent,則可能需要使用這個(gè)循環(huán):
BEGIN for i in 1..1000000 loop EXECUTE IMMEDIATE alter table scott.s allocate extent (DATAFILE || E:\xxxx\test.ORA || SIZE 64K) end loop; end ; /
繼續(xù)分配空間直到壞塊成為 scott.s 的一部分 mdash; 使用以下查詢進(jìn)行檢查:
SQL select segment_name, segment_type, owner from dba_extents where file_id = Absolute file number and corrupt block number between block_id and block_id + blocks -1 ;
第 8 步 – 向虛擬表中插入數(shù)據(jù)以格式化塊
示例代碼(取決于表空間的大小,循環(huán)的次數(shù)可能發(fā)生變化):
BEGIN FOR i IN 1..1000000000 LOOP INSERT /*+ APPEND */ INTO scott.s select i, lpad(REFORMAT ,3092, R) from dual; commit ; END LOOP; END;
或者
BEGIN FOR i IN 1..1000000000 LOOP INSERT INTO scott.s VALUES(i, x END LOOP; END; /
或使用以下包含 2 個(gè)循環(huán)的代碼:
Begin FOR i IN 1..1000000000 loop for j IN 1..1000 loop Insert into scott.s VALUES(i, x end loop; commit; END LOOP; END;
每向表中插入一行就會(huì)觸發(fā)觸發(fā)器,且一旦向壞塊中插入 *** 行數(shù)據(jù),就會(huì)產(chǎn)成 ORA-20000 異常。
第 9 步 – 通過運(yùn)行 DBV 和 Rman 備份確定數(shù)據(jù)文件中的壞塊情況
運(yùn)行 dbverify 或 RMAN 在損壞的數(shù)據(jù)文件 (或整個(gè)數(shù)據(jù)庫) 上再次驗(yàn)證。它不會(huì)顯示塊損壞。
確保你做兩次手動(dòng)日志切換或檢查點(diǎn),使得在內(nèi)存中的信息寫入到磁盤。
RMAN 備份不會(huì)報(bào)告此塊上的任何錯(cuò)誤。
運(yùn)行真實(shí)的備份操作之前,你可以在數(shù)據(jù)文件上重新運(yùn)行 RMAN validate 命令,并檢查 v$database_block_corruption 不再顯示塊被標(biāo)記為損壞。
對于數(shù)據(jù)庫版本 =10gR2
Rman Backup validate check logical datafile fileno , fileno ;
對于數(shù)據(jù)庫版本 =11gR1
Rman Backup validate check logical datafile fileno ;
或
Rman validate datafile fileno block blockno reported corrupt , blockno reported corrupt ;
一旦完成
SQL SELECT * FROM V $ DATABASE_BLOCK_CORRUPTION;
第 10 步 – 刪除第 4 步中創(chuàng)建的虛擬表
SQL DROP TABLE scott.s ;
如果版本為 10gr1 及以上,同時(shí)使用 purge 選項(xiàng)以清空回收站
第 11 步 ndash; 執(zhí)行手動(dòng)日志切換和檢查點(diǎn)
執(zhí)行兩次日志切換和檢查點(diǎn),以便將在內(nèi)存中格式化的塊寫入到磁盤并使 dbverify 不再報(bào)告錯(cuò)誤
SQL Alter system switch logfile ; -- Do this couple of time SQL Alter system checkpoint ;
第 12 步 – 刪除第 6 步中創(chuàng)建的觸發(fā)器
SQL DROP triggercorrupt_trigger ;
看完上述內(nèi)容,你們掌握 oracle 數(shù)據(jù)庫中如何格式化不屬于任何段的損壞塊的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道,感謝各位的閱讀!