25 破損データの修復

データ・ブロックの破損を検出し、修正できます。

ノート:

DBMS_REPAIRパッケージについて詳しくない場合は、このパッケージに含まれる修復プロシージャを実行する際に、Oracleサポート・サービスのアナリストと共同で作業することをお薦めします。

25.1 データ・ブロック破損を修復するオプション

Oracle Databaseには、データ・ブロックの破損を検出して修正するために、複数の方法が用意されています。

その1つは、破損の検出後にオブジェクトを削除して再作成することです。しかし、この方法が必ずしも可能とはかぎらず、またそれが望ましくない場合もあります。データ・ブロックの破損が行のサブセットにかぎられている場合は、破損した行を除くすべてのデータを選択して表を再作成する方法があります。

また、DBMS_REPAIRパッケージを使用してデータ・ブロック破損を管理する方法もあります。DBMS_REPAIRを使用すると、表と索引の破損ブロックを検出して修復できます。オブジェクトは、再作成または修復の試行中でも続けて使用できます。

Recovery Manager (RMAN)のコマンドRECOVER BLOCKを使用して、破損したデータ・ブロックまたはデータ・ブロックのセットを修復することもできます。

ノート:

データの損失を伴う破損の場合は、そのデータがデータベース・システム全体にどのように格納されているかを分析して理解する必要があります。修復の内容によっては、データを失ったり、論理的一貫性が損なわれる場合があります。このパッケージで提供される修復アプローチが特定の破損に対して適切かどうかを個々に判断する必要があります。

関連項目:

RMANのRECOVER BLOCKコマンドの詳細は、『Oracle Databaseバックアップおよびリカバリ・リファレンス』を参照してください。

25.2 DBMS_REPAIRパッケージの内容

DBMS_REPAIRパッケージには、データ破損修復プロシージャが含まれており、表および索引にある破損ブロックを検出して修復できます。

関連項目:

DBMS_REPAIRプロシージャの構文、制限事項および例外の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

25.2.1 DBMS_REPAIRプロシージャ

DBMS_REPAIRパッケージのプロシージャにより、破損したブロックを検出および修復できます。

次の表は、DBMS_REPAIRパッケージに含まれているプロシージャの一覧を示します。

プロシージャ名 説明

ADMIN_TABLES

修復表および孤立キー表の管理機能(作成、削除、パージ)を提供します。

ノート: これらの表は常にSYSスキーマに作成されます。

CHECK_OBJECT

表または索引の破損を検出し、レポートします。

DUMP_ORPHAN_KEYS

破損データ・ブロック内の行を指す索引エントリをレポートします。

FIX_CORRUPT_BLOCKS

すでにCHECK_OBJECTプロシージャで破損ブロックとして識別されているブロックにソフトウェア破損を示すマークを付けます。

REBUILD_FREELISTS

オブジェクトの空きリストを再作成します。

SEGMENT_FIX_STATUS

セグメント領域管理がAUTOの場合に、ビットマップ・エントリの破損状態を修正する機能を提供します。

SKIP_CORRUPT_BLOCKS

このプロシージャを使用すると、表と索引のスキャン時に、破損マークが付いたブロックが無視されます。使用しない場合は、破損マークが付いたブロックが検出されたときにエラーORA-01578が返されます。

これらのプロシージャの詳細と使用例は、「DBMS_REPAIRの例」を参照してください。

25.2.2 DBMS_REPAIRプロシージャに関する制限事項

いくつかの制限および制約事項がDBMS_REPAIRプロシージャに適用されます。

DBMS_REPAIRプロシージャには、次の制約があります。

  • LOBデータ型、ネストした表およびVARRAYを含む表はサポートされますが、表外格納の列は無視されます。

  • クラスタは、SKIP_CORRUPT_BLOCKSおよびREBUILD_FREELISTSプロシージャではサポートされますが、CHECK_OBJECTプロシージャではサポートされません。

  • 索引構成表およびLOB索引はサポートされません。

  • グローバル一時表はサポートされていません。

  • DUMP_ORPHAN_KEYSプロシージャは、ビットマップ索引またはファンクション索引には機能しません。

  • DUMP_ORPHAN_KEYSプロシージャで処理される最大キー長は、3,950バイトです。

25.3 DBMS_REPAIRパッケージの使用方法

データ・ブロックの破損に対処するために、DBMS_REPAIRパッケージを使用できます。

25.3.1 タスク1: 破損の検出とレポート

最初のタスクでは、破損を検出しレポートします。レポートでは、ブロックに関する問題が明らかになるだけでなく、それに対応する修復ディレクティブも識別されます。

25.3.1.1 破損の検出とレポートについて

破損を検出するには、いくつかの方法があります。

表25-1に、異なる検出方法を示します。

表25-1 破損検出方法の比較

検出方法 説明

DBMS_REPAIR PL/SQLパッケージ

指定した表、パーティションまたは索引のブロック・チェックを実行します。修復表に結果を移入します。

DB_VERIFYユーティリティ

オフライン・データベースでブロック・チェックを実行します。

ANALYZE TABLE SQL文

VALIDATE STRUCTUREオプションを指定すると、索引、表またはクラスタの構造の整合性がANALYZE TABLE文によって検証され、表と索引が同期しているかどうかがチェックまたは検証されます。

DB_BLOCK_CHECKING初期化パラメータ

DB_BLOCK_CHECKING=TRUEの場合は、実際に破損マークを付ける前に、破損ブロックが識別されます。チェックは、ブロックの変更時に実行されます。

25.3.1.2 DBMS_REPAIR: CHECK_OBJECTおよびADMIN_TABLESプロシージャの使用

CHECK_OBJECTプロシージャは、指定されたオブジェクトのブロック破損をチェックしてレポートします。ADMIN_TABLESプロシージャは、破損の修正を円滑に行うために修復表を作成します。

CHECK_OBJECTプロシージャでは、索引と表に対するANALYZE...VALIDATE STRUCTURE文と同様に、索引とデータ・ブロックに対してブロック・チェックが実行されます。

CHECK_OBJECTでは、破損がレポートされるだけでなく、そのオブジェクトに対して後でFIX_CORRUPT_BLOCKSを実行した場合に行われる修正も識別されます。この情報は修復表への移入によって使用可能になるため、最初にADMIN_TABLESプロシージャで修復表を作成しておく必要があります。

CHECK_OBJECTプロシージャを実行した後は、修復表の簡単な問合せによってそのオブジェクトの破損および修復ディレクティブが表示されます。この情報に基づいて、レポートされた問題に最も適切な対処方法を評価できます。

25.3.1.3 DB_VERIFY: オフライン・データベース・チェックの実行

データ破損が発生した場合は、オフライン診断ユーティリティとしてDB_VERIFYを使用します。

関連項目:

DB_VERIFYの詳細は、『Oracle Databaseユーティリティ』を参照してください。

25.3.1.4 ANALYZE: 破損のレポート

ANALYZE TABLE...VALIDATE STRUCTURE文は、分析するオブジェクトの構造の妥当性をチェックします。オブジェクトの構造内で破損が検出されると、エラー・メッセージが表示されます。この場合、オブジェクトを削除して作成しなおす必要があります。

ANALYZE TABLE文のCASCADE句を使用すると、1回の操作で、表とすべての索引の構造をチェックできます。この操作ではリソースを大量に消費する可能性があるため、軽量なチェックを実行するFASTオプションを使用できます。詳細は、「表、索引、クラスタおよびマテリアライズド・ビューの妥当性チェック」を参照してください。

関連項目:

25.3.1.5 DB_BLOCK_CHECKING初期化パラメータ

DB_BLOCK_CHECKING初期化パラメータをTRUEに設定すると、データベースのブロック・チェックを使用可能にすることができます。

これにより、データ・ブロックおよび索引ブロックが変更された際には、必ずそのブロックの内部一貫性がチェックされます。DB_BLOCK_CHECKINGは、ALTER SYSTEM SET文で変更可能な動的パラメータです。システム表領域では、ブロック・チェックは常に使用可能になっています。

関連項目:

DB_BLOCK_CHECKING初期化パラメータの詳細は、『Oracle Databaseリファレンス』を参照してください。

25.3.2 タスク2: DBMS_REPAIRの使用に伴うコストと利点の評価

DBMS_REPAIRを使用する前に、その利害得失を検討する必要があります。また、破損オブジェクトの対応手段として使用可能な他のオプションも検討してください。

次の質問に答えることから開始してください。

  • 破損の範囲はどの程度ですか。

    破損の有無と修復アクションの要不要を判断するには、CHECK_OBJECTプロシージャを実行して修復表を問い合せます。

  • ブロック破損の対応手段として使用可能な他のオプションがありますか。次のことを考慮してください。

    • 他のソースからのデータが使用可能な場合は、そのオブジェクトを削除し、再作成して再移入する。

    • CREATE TABLE...AS SELECT文を発行して、破損表から新しい表を作成する。

    • SELECT文から破損行を除外して、破損を無視する。

    • メディア・リカバリを実行します。

  • DBMS_REPAIRを使用してオブジェクトを使用可能にした場合に、どのような論理的な破損や副作用が生じますか。それらの問題に対処できますか。そのためにはどんな作業が必要ですか。

    破損マークが付いたブロックの行にはアクセスできない場合があります。また、正常にアクセスできる行が含まれているブロックでも、破損マークが付いている場合があります。

    ブロックに破損マークが付いている場合は、参照整合性制約が壊れていることがあります。この場合は、制約を使用禁止にし、再び使用可能にすると、不整合がレポートされます。すべての問題を解決すれば、再び制約を使用できるようになります。

    表にトリガーが定義されている場合は、論理的な破損が生じることがあります。たとえば、行を再度挿入したときに、挿入トリガーが起動されるかどうかを確認します。これらの問題に対処するには、インストレーションでどのトリガーがどのように使用されているかを理解する必要があります。

    索引と表が同期化されていない場合は、DUMP_ORPHAN_KEYSプロシージャを実行して、破損データの再作成に役立つ情報をキーから取得します。次に、ALTER INDEX...REBUILD ONLINE文を発行し、表と索引を同期化します。

  • 修復によってデータが失われる場合に、このデータを取り出すことができますか。

    データ・ブロックに破損マークが付いている場合は、索引からデータを取り出すことができます。この情報を取り出すには、DUMP_ORPHAN_KEYSプロシージャを利用します。

25.3.3 タスク3: オブジェクトの使用可能化

DBMS_REPAIRを使用して表と索引のスキャン時に破損を無視することにより、オブジェクトを使用可能にします。

25.3.3.1 破損の修復: FIX_CORRUPT_BLOCKSおよびSKIP_CORRUPT_BLOCKSプロシージャの使用

DBMS_REPAIRの機能の適用範囲外にある破損をスキップする環境を設定し、それによって破損オブジェクトを使用可能にできます。

破損が、データ・ブロック内の不良行などのデータの損失を伴う場合は、FIX_CORRUPT_BLOCKSプロシージャによって、そのようなブロックすべてに破損マークが付けられます。次に、破損マークが付いたブロックをスキップするSKIP_CORRUPT_BLOCKSプロシージャを実行できます。SKIP_FLAGパラメータがプロシージャに設定されている場合は、破損マークが付いているすべてのブロックが、表と索引のスキャンでスキップされます。これはメディアとソフトウェアの両方の破損ブロックに適用されます。

25.3.3.2 破損ブロックをスキップする操作の意味

破損したブロックをスキップすると、いくつかの状況では、問合せから異なる結果が返されることがあります。

索引と表が同期化されていない場合、ある問合せで索引のみをプローブし、後続の問合せで索引と表の両方をプローブするような状況下では、SET TRANSACTION READ ONLYトランザクションの一貫性が保たれないことがあります。表ブロックに破損マークが付いている場合、この2つの問合せは異なる結果を返すので、読取り専用トランザクションのルールに違反します。この場合の対処方法の1つとして、SET TRANSACTION READ ONLYトランザクション内で破損をスキップしないようにします。

これと同様の問題は、連鎖している行の選択時にも発生します。同じ行を問い合せても、破損にアクセスできる場合とできない場合があるため、異なった結果が生じます。

25.3.4 タスク4: 破損の修復および失われたデータの再作成

オブジェクトを使用可能にした後で、次の修復アクティビティを実行します。

25.3.4.1 DUMP_ORPHAN_KEYSプロシージャを使用したデータのリカバリ

DUMP_ORPHAN_KEYSプロシージャは、破損データ・ブロック内の行を指す索引エントリをレポートします。この種の索引エントリがすべて、破損のキーとROWIDを格納する孤立キー表に挿入されます。

索引エントリ情報を取り出した後、ALTER INDEX...REBUILD ONLINE文を使用して索引を再作成できます。

25.3.4.2 SEGMENT_FIX_STATUSプロシージャを使用したセグメント・ビットマップの修正

セグメントの空き領域の管理にビットマップが使用されている場合(SEGMENT SPACE MANAGEMENT AUTO)、SEGMENT_FIX_STATUSプロシージャを使用します。

このプロシージャは、対応するブロックの現在の内容に基づいてビットマップ・エントリの状態を再計算します。また、ビットマップ・エントリを特定の値に設定するように指定することもできます。通常は、状態が適切に再計算されるので、値を強制的に設定する必要はありません。

25.4 DBMS_REPAIRの例

DBMS_REPAIRパッケージの使用方法の例を示します。

25.4.1 例: 修復表または孤立キー表の作成

修復表は、破損に関する情報を提供します。孤立キー表は、破損した行を指す索引エントリに関する情報を提供します。

25.4.1.1 修復表または孤立キー表について

ADMIN_TABLEプロシージャは、修復表または孤立キー表の作成、パージまたは削除に使用します。

修復表は、CHECK_OBJECTプロシージャによって検出された破損の内容と、FIX_CORRUPT_BLOCKSプロシージャを実行した場合にこれらの破損がどのように処理されるかを示す情報を提供します。また、FIX_CORRUPT_BLOCKSプロシージャの実行が必要かを判断する際にも使用されます。

孤立キー表は、DUMP_ORPHAN_KEYSプロシージャの実行時に使用され、破損行を指す索引エントリが格納されます。DUMP_ORPHAN_KEYSプロシージャは、そのアクティビティをロギングし、索引情報を使用可能な形にして、孤立キー表に移入します。

25.4.1.2 例: 修復表の作成

ADMIN_TABLESプロシージャを使用して修復表を作成する例を示します。

次の例では、users表領域の修復表を作成しています。

BEGIN
  DBMS_REPAIR.ADMIN_TABLES (
     TABLE_NAME => 'REPAIR_TABLE',
     TABLE_TYPE => dbms_repair.repair_table,
     ACTION     => dbms_repair.create_action,
     TABLESPACE => 'USERS');
END;
/

修復表または孤立キー表それぞれについて、存在しなくなったオブジェクトに関連する行を除外するビューも作成されます。ビュー名は、修復表または孤立キー表の名前に対応しており、接頭辞DBA_が付いています(たとえば、DBA_REPAIR_TABLEDBA_ORPHAN_KEY_TABLE)。

次の問合せでは、users表領域に作成された修復表が表示されます。

DESC REPAIR_TABLE

 Name                         Null?    Type
 ---------------------------- -------- --------------
 OBJECT_ID                    NOT NULL NUMBER
 TABLESPACE_ID                NOT NULL NUMBER
 RELATIVE_FILE_ID             NOT NULL NUMBER
 BLOCK_ID                     NOT NULL NUMBER
 CORRUPT_TYPE                 NOT NULL NUMBER
 SCHEMA_NAME                  NOT NULL VARCHAR2(128)
 OBJECT_NAME                  NOT NULL VARCHAR2(128)
 BASEOBJECT_NAME                       VARCHAR2(128)
 PARTITION_NAME                        VARCHAR2(128)
 CORRUPT_DESCRIPTION                   VARCHAR2(2000)
 REPAIR_DESCRIPTION                    VARCHAR2(200)
 MARKED_CORRUPT               NOT NULL VARCHAR2(10)
 CHECK_TIMESTAMP              NOT NULL DATE
 FIX_TIMESTAMP                         DATE
 REFORMAT_TIMESTAMP                    DATE
25.4.1.3 例: 孤立キー表の作成

ADMIN_TABLESプロシージャを使用して孤立キー表を作成する例を示します。

次の例は、users表領域の孤立キー表の作成方法を示しています。

BEGIN
  DBMS_REPAIR.ADMIN_TABLES (
     TABLE_NAME => 'ORPHAN_KEY_TABLE',
     TABLE_TYPE => dbms_repair.orphan_table,
     ACTION     => dbms_repair.create_action,
     TABLESPACE => 'USERS');
END;
/

次の問合せでは、孤立キー表の定義を表示しています。

DESC ORPHAN_KEY_TABLE

 Name                         Null?    Type
 ---------------------------- -------- -----------------
 SCHEMA_NAME                  NOT NULL VARCHAR2(128)
 INDEX_NAME                   NOT NULL VARCHAR2(128)
 IPART_NAME                            VARCHAR2(128)
 INDEX_ID                     NOT NULL NUMBER
 TABLE_NAME                   NOT NULL VARCHAR2(128)
 PART_NAME                             VARCHAR2(128)
 TABLE_ID                     NOT NULL NUMBER
 KEYROWID                     NOT NULL ROWID
 KEY                          NOT NULL ROWID
 DUMP_TIMESTAMP               NOT NULL DATE

25.4.2 例: 破損の検出

CHECK_OBJECTプロシージャによって破損を検出する例を示します。

CHECK_OBJECTプロシージャは、指定されたオブジェクトをチェックし、破損および修復ディレクティブに関する情報を修復表に移入します。オブジェクトの一部をチェックする場合は、必要に応じて、範囲、パーティション名またはサブパーティション名を指定できます。

妥当性チェックでは、オブジェクト内部でそれまでに破損マークが付けられていないブロックがすべてチェックされます。ブロックごとに、トランザクションおよびデータ・レイヤー部分の自己整合性がチェックされます。CHECK_OBJECTの実行中に、破損バッファ・キャッシュ・ヘッダーを持つブロックが検出されると、そのブロックはスキップされます。

scott.dept表に対するCHECK_OBJECTプロシージャの実行例を次に示します。

SET SERVEROUTPUT ON
DECLARE num_corrupt INT;
BEGIN
 num_corrupt := 0;
 DBMS_REPAIR.CHECK_OBJECT (
     SCHEMA_NAME => 'SCOTT',
     OBJECT_NAME => 'DEPT',
     REPAIR_TABLE_NAME => 'REPAIR_TABLE',
     CORRUPT_COUNT =>  num_corrupt);
 DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt));
END;
/

SQL*Plusには、1つの破損を示す次の行が出力されます。

number corrupt: 1

修復表を問い合せると、破損の説明および修復アクションに関する提案を含む情報が表示されます。

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
------------------------------------------------------------------------------
DEPT                                    3            1 FALSE
kdbchk: row locked by non-existent transaction
        table=0   slot=0
        lockid=32   ktbbhitc=1
mark block software corrupt

まだ破損ブロックに破損マークが付いていないため、ここで重要なデータを抽出します。ブロックに破損マークが付けられた後は、そのブロック全体がスキップされます。

25.4.3 例: 破損ブロックの修正

FIX_CORRUPT_BLOCKSプロシージャによって破損ブロックを修正する例を示します。

CHECK_OBJECTプロシージャによって生成した修復表内の情報に基づいて、FIX_CORRUPT_BLOCKSプロシージャを使用し、指定したオブジェクトの破損ブロックを修正します。ブロックの変更前には、そのブロックがまだ破損状態にあるかどうかが確認されます。破損ブロックは、そのブロックにソフトウェア破損のマークを付けることによって修復されます。修復が実行されると、修復表内の対応する行がタイムスタンプ付きで更新されます。

次の例では、CHECK_OBJECTプロシージャによってレポートされた表scott.deptの破損ブロックを修正しています。

SET SERVEROUTPUT ON
DECLARE num_fix INT;
BEGIN 
 num_fix := 0;
 DBMS_REPAIR.FIX_CORRUPT_BLOCKS (
     SCHEMA_NAME => 'SCOTT',
     OBJECT_NAME=> 'DEPT',
     OBJECT_TYPE => dbms_repair.table_object,
     REPAIR_TABLE_NAME => 'REPAIR_TABLE',
     FIX_COUNT=> num_fix);
 DBMS_OUTPUT.PUT_LINE('num fix: ' || TO_CHAR(num_fix));
END;
/

SQL*Plusでは次の行が出力されます。

num fix: 1

次の問合せによって、修復が完了していることが確認されます。

SELECT OBJECT_NAME, BLOCK_ID, MARKED_CORRUPT
     FROM REPAIR_TABLE;

OBJECT_NAME                      BLOCK_ID MARKED_COR
------------------------------ ---------- ----------
DEPT                                    3 TRUE

25.4.4 例: 破損データ・ブロックを指す索引エントリの検索

DUMP_ORPHAN_KEYSプロシージャを使用して破損データ・ブロックを指す索引エントリを検索する例を示します。

DUMP_ORPHAN_KEYSプロシージャは、破損データ・ブロック内の行を指す索引エントリをレポートします。索引エントリごとに、指定した孤立キー表に1行ずつ挿入されます。この孤立キー表は、事前に作成しておく必要があります。

この情報は、表内の失われた行を再作成する場合や診断に使用します。

ノート:

このプロシージャは、修復表で識別された表に対応付けられている索引ごとに実行する必要があります。

この例では、pk_deptscott.dept表の索引です。これがスキャンされて、破損したデータ・ブロックの行を指す索引エントリがあるかどうかが見極められます。

SET SERVEROUTPUT ON
DECLARE num_orphans INT;
BEGIN
 num_orphans := 0;
 DBMS_REPAIR.DUMP_ORPHAN_KEYS (
     SCHEMA_NAME => 'SCOTT',
     OBJECT_NAME => 'PK_DEPT',
     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;
/

次の出力は、孤立キーが3つあることを示しています。

orphan key count: 3

孤立キー表の索引エントリは、索引の再作成が必要であることを示しています。索引の再作成により、表プローブと索引プローブが同じ結果セットを返すことが保証されます。

25.4.5 例: 破損ブロックのスキップ

SKIP_CORRUPT_BLOCKSプロシージャを使用して破損ブロックをスキップする例を示します。

SKIP_CORRUPT_BLOCKSプロシージャは、指定されたオブジェクトの索引および表のスキャン時に破損ブロックをスキップするかしないかを指定します。オブジェクトが表であれば、スキップは表とその索引に適用されます。オブジェクトがクラスタのときは、クラスタ内のすべての表およびその各索引に適用されます。

次の例では、scott.dept表のソフトウェア破損ブロックのスキップを可能に設定しています。

BEGIN
  DBMS_REPAIR.SKIP_CORRUPT_BLOCKS (
     SCHEMA_NAME => 'SCOTT',
     OBJECT_NAME => 'DEPT',
     OBJECT_TYPE => dbms_repair.table_object,
     FLAGS => dbms_repair.skip_flag);
END;
/

DBA_TABLESビューを使用してscottの表を問い合せると、表scott.deptSKIP_CORRUPTが使用可能になっていることが示されます。

SELECT OWNER, TABLE_NAME, SKIP_CORRUPT FROM DBA_TABLES
    WHERE OWNER = 'SCOTT';

OWNER                          TABLE_NAME                     SKIP_COR
------------------------------ ------------------------------ --------
SCOTT                          ACCOUNT                        DISABLED
SCOTT                          BONUS                          DISABLED
SCOTT                          DEPT                           ENABLED
SCOTT                          DOCINDEX                       DISABLED
SCOTT                          EMP                            DISABLED
SCOTT                          RECEIPT                        DISABLED
SCOTT                          SALGRADE                       DISABLED
SCOTT                          SCOTT_EMP                      DISABLED
SCOTT                          SYS_IOT_OVER_12255             DISABLED
SCOTT                          WORK_AREA                      DISABLED

10 rows selected.