Email: service@parnassusdata.com 7 x 24 online support!
Oracle DBMS_REPAIRパッケージの使用例
ORACLEデータベース によくあるエラ の解決策
プロのOracle Databaseの復旧サービスを提供
携帯番号: +86 13764045638 メール:service@parnassusdata.com
[質問] DBMS_REPAIRパッケージの使用方法について障害発生からの手順を踏まえて教えてください。 [回答] データブロック破損の障害が発生した場合は、適切なバックアップからリカバリを行い対 応するのが原則です。 しかし、運用のミスなどによりリカバリが行えない場合、DBMS_REPAIRパッケージにより 破損ブロックを読み飛ばすように設定することができます。 ※ DBMS_REPAIRパッケージは破損したデータを修復するものではありません。以下の例で も失われるデータがあります。 [実施環境] <表定義> SQL> create table test (c1 number, c2 char(100)); SQL> begin for i in 1..1000 loop insert into test values (i, i); commit; end loop; end; / SQL> create index i_test on test(c1); [障害発生] (1)障害発生 SQL> select * from test where c1 = 1; select * from test where c1 = 1 * 1行でエラーが発生しました。 ORA-01578: ファイル番号 5,ブロック番号 275でOracleデータ・ブロックに障害が発生しました。 ORA-01110: データ・ファイル 5 : SQL> analyze table test validate structure cascade; analyze table test validate structure cascade * 1行でエラーが発生しました。 ORA-01578: ファイル番号 5,ブロック番号 275でOracleデータ・ブロックに障害が発生しました。 ORA-01110: データ・ファイル 5 : (2)Repair Table/Orphan Tableの作成 ※ まず、障害状況を捕捉するための表(REPAIR_TABLE/ORPHAN_KEY_TABLE)を作成します。 SQL> connect sys/<sys_password> SQL> begin dbms_repair.admin_tables ( table_name => 'REPAIR_TABLE', table_type => dbms_repair.repair_table, action => dbms_repair.create_action, tablespace => 'USERS'); end; / SQL> begin dbms_repair.admin_tables ( table_name => 'ORPHAN_KEY_TABLE', table_type => dbms_repair.orphan_table, action => dbms_repair.create_action, tablespace => 'USERS'); end; / (3)破損オブジェクトの確認 ※ dbms_repair.check_objectにより指定したオブジェクトの検証を行い、破損状況お よび修復指示に関する情報を指定した表(REPAIR_TABLE)に格納します。 SQL> set serveroutput on SQL> declare num_corrupt INT; begin num_corrupt := 0; dbms_repair.check_object ( schema_name => 'TEST', object_name => 'TEST', repair_table_name => 'REPAIR_TABLE', corrupt_count => num_corrupt); dbms_output.put_line('num :'|| to_char(num_corrupt)); end; / num :1 ※ 上記実行結果より1つのデータブロックが破損していることを確認できました。 次に、破損状況等をREPAIR_TABLEから確認します。 SQL> select object_name, block_id, corrupt_type, marked_corrupt, corrupt_description, repair_description from repair_table; OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_COR ------------------------------ ---------- ------------ ---------- CORRUPT_DESCRIPTION -------------------------------------------------------------------------------- REPAIR_DESCRIPTION -------------------------------------------------------------------------------- TEST 275 6148 FALSE mark block software corrupt (4)破損ブロックの修正(対象データブロックに破損マークをつけます) SQL> set serveroutput on SQL> declare num_fix INT; begin num_fix := 0; dbms_repair.fix_corrupt_blocks ( schema_name => 'TEST', object_name => 'TEST', object_type => dbms_repair.table_object, repair_table_name => 'REPAIR_TABLE', fix_count => num_fix); dbms_output.put_line('num fixed :'|| to_char(num_fix)); end; / num fixed :1 PL/SQLプロシージャが正常に完了しました。 (5)破損マークがついたことの確認 SQL> select object_name, block_id, corrupt_type, marked_corrupt, corrupt_description, repair_description from repair_table; OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_COR ------------------------------ ---------- ------------ ---------- CORRUPT_DESCRIPTION -------------------------------------------------------------------------------- REPAIR_DESCRIPTION -------------------------------------------------------------------------------- TEST 275 6148 TRUE mark block software corrupt ※ MARKED_CORRUPT列がTRUEにかわったことが確認できます。 (6)破損データブロック関連の索引エントリの確認 SQL> set serveroutput on SQL> declare num_orphans INT; begin num_orphans := 0; dbms_repair.dump_orphan_keys ( schema_name => 'TEST', object_name => 'I_TEST', object_type => dbms_repair.index_object, repair_table_name => 'REPAIR_TABLE', orphan_table_name => 'ORPHAN_KEY_TABLE', key_count => num_orphans); dbms_output.put_line('orphan key count :'|| to_char(num_orphans)); end; / orphan key count :7 PL/SQLプロシージャが正常に完了しました。 ※ 上記のとおり破損ブロックに対応する索引エントリが7つ存在することを確認できま す。このように破損ブロックに対応する索引エントリが存在する場合は索引の再作 成が必要となります。(手順(8)) (7)対象オブジェクトのスキップ指定 破損ブロックに破損マークをつけただけではまだ検索時に以下のエラーが発生します。 スキップ指定することで対象オブジェクトへのアクセスを可能にします。 SQL> select * from test.test where c1 = 1; select * from test.test where c1 = 1 * 1行でエラーが発生しました。 ORA-01578: ファイル番号 5,ブロック番号 275でOracleデータ・ブロックに障害が発生しました。 ORA-01110: データ・ファイル 5 : SQL> begin dbms_repair.skip_corrupt_blocks ( schema_name => 'TEST', object_name => 'TEST', object_type => dbms_repair.table_object, flags => dbms_repair.skip_flag); end; / PL/SQLプロシージャが正常に完了しました。 SQL> select table_name, skip_corrupt from dba_tables where owner='TEST' and table_name = 'TEST'; TABLE_NAME SKIP_COR ------------------------------ -------- TEST ENABLED 以上により対象オブジェクトへのアクセスが可能になりますが、破損マークがつけられ、 検索時にスキップしたブロックに格納されているデータは読み飛ばされていることを以 下よりも確認できます。 SQL> select count(*) from test.test; COUNT(*) ---------- 993 (当初1000件のデータを格納していますので7件のデータが失われたことを意味します。) (8)索引の再作成 SQL> alter index test.i_test rebuild online; 索引が変更されました。 (9)フリーリストの再編成 SQL> begin dbms_repair.rebuild_freelists ( schema_name => 'TEST', object_name => 'TEST', object_type => dbms_repair.table_object); end; / PL/SQLプロシージャが正常に完了しました。 自動セグメント領域管理の場合は(9)のオペレーションは不要となります。 自動セグメント領域管理の場合にて(9)のオペレーションを実施した場合は ORA-10614 が発生致します。ただしこのエラーは無視して頂いて問題ありま せん。 [参考資料] 『Oracle8i 管理者ガイド』20章 データ・ブロック破損への対処 『Oracle9i 管理者ガイド』22章 データ・ブロック破損の検出と修復 『Oracle8i PL/SQL パッケージ・プロシージャリファレンス』36章 DBMS_REPAIR 『Oracle9i PL/SQL パッケージ・プロシージャリファレンス』47章 DBMS_REPAIR