Email: service@parnassusdata.com 7 x 24 online support!

    You are here

Oracle ORA-1410 の主な発生原因とその対処方法について

Oracle ORA-1410 の主な発生原因とその対処方法について

 

ORACLEデータベース によくあるエラ の解決策

プロのOracle Databaseの復旧サービスを提供
携帯番号: +86 13764045638 メール:service@parnassusdata.com

 

[エラー・メッセージ]

ORA-01410: ROWIDが無効です。 


[技術的説明]

- ROWID の説明

 ROWID は行に直接アクセスするためのアドレスです。ROWID には、オブジェ
 クト番号、相対ファイル番号、ブロック番号、ブロックのスロット番号の情報
 が含まれます。

 Oracle8 以降のバージョンでは、以下の形式となっています。
 
 -------------------------------
 OOOOOOFFFBBBBBBSSS
 O:オブジェクト番号 (データ長:6)
 F:相対ファイル番号 (データ長:3)
 B:ブロック番号 (データ長:6)
 S:スロット番号 (データ長:3)
 -------------------------------

- エラー内容説明

 ORA-1410 は ROWID が不正であることを示します。

 ROWID の解析時に、該当の行が存在しないと ORA-1410 が発生する可能性が
 あります。

 - 相対ファイル番号およびブロック番号は正しいが、行スロットが存在しな
  い場合には「レコードが選択されませんでした」というメッセージが返さ
  れます。
 - スロット番号以外の箇所に問題がある場合、ORA-1410 が返されます。


[ORA-1410 の主な発生原因]

1.ブロック破損により発生

2. ROWID の破損により発生

 ROWID が破損した場合、ROWID のコピー(例:索引)、また上書きされた 
 ROWID が示す表が破損する可能性があります。索引が破損した場合、索引に
 は誤った ROWID が格納されているために、行データにアクセスした時に 
 ORA-1410 が発生します。同様に、もし行データが破損した場合、ブロック・
 アドレスが上書きされ、索引に格納された正しい ROWID では、行データを
 見つけることができなくなります。

 ROWID の破損には以下の原因が考えられます。

  2-1.SQL文によって誤った ROWID が挿入された、またはユーザが作成した
    PL/SQLプロシージャの誤ったロジックによって不正な ROWID が生成され
    た。

  2-2.ハードウェア障害により、内部的に生成された ROWID がメモリ上で破損
    した。
    この場合、OS エラーのメッセージを確認してください。

  2-3.破損した索引から ROWID を読み込んだ。
    このケースでは、多くの場合 ORA-1410 に伴って、その他の破損に関す
    るエラーが返されます。
 
  2-4.長時間かかる検索を実行中に、検索対象のオブジェクトに対して DDL文
   を実行した。
    例えば、索引を利用した検索を実行中に、その索引を再作成すると 
    ORA-1410 が発生します。

  2-5.ROWID は正しいが、データ・ブロックまたはデータファイルが上書きさ
    れて破損し、ブロック・アドレスが不正になった。
    このケースでは、多くの場合 ORA-1410 に伴って、その他の破損に関す
    るエラーが返されます。

  2-6.ROWID は正しいが、直前にポインタが動いた。
    SQL文の実行中に、表が切り捨てられた時などに発生します。これは、
    SQL文はキャッシュされた ROWID を使用してアクセスしようするのに対し、
    ブロックは表の切り捨てによって削除されているためです。
    SQL文の実行中に、表パーティションの交換が行われた時にも同様の事象
    が発生します。
   
  2-7.Oracle、OS の不具合や、その他アプリケーションの不具合によるもの。
   Oracle の不具合である場合は、日本オラクルカスタマーサポートセンター
   に連絡してください。  


[現象発生時の対処方法]

1.エラーの再現が可能か確認

 ORA-1410 の再現が可能であれば、トレース・ファイルを取得します。
 トレース・ファイルが生成されない場合には、強制的に取得する必要があり
 ます。
 トレース・ファイルを強制的に取得するには、エラースタック・イベントを
 セットし、エラーを再現します。

 エラースタック・イベントは以下のように設定します。

  SQL> alter system set events '1410 trace name ERRORSTACK level 3';
  
 トレース・ファイルから失敗した SQL文を特定します。失敗した SQL文は
 トレース・ファイルの上部に記されています。トレース・ファイルの解析が
 難しい場合は 日本オラクルカスタマーサポートセンター連絡し、トレース・
 ファイルを提供してください。

2.エラーが再現しない場合

 もし再現できない場合は、エラーが発生した時刻の前後に表の切り捨て、
 または表パーティションの交換を実行していないかを確認します。
 もしどちらかを実行していた場合は、エラーは一時的なものです。該当の表
 を読み込んでいる間は表の切り捨て、表パーティションの交換は行わないよ
 うにしてください。スケジュールを見直すことをお勧めします。

3.エラーが再現可能な場合

 ORA-1410 が再現可能な場合、失敗した SQL文でアクセスしている表を特定
 します。SQL文 の FROM句で指定している表が該当の表です。もしビューを
 参照している場合には、ビューの定義から元となっている表を探します。
 
4.表と索引の検証

 3 で特定した表が破損しているか調べるために検証を実行します。
 "ANALYZE ・・・ VALIDATE" は表のロックが必要になります。もしユーザが
 表を更新するためにアクセスしている場合は、ユーザの処理が終わるまで
 VALIDATE 実行することはできません。もし VALIDATE を実行できた場合は、
 VALIDATE が終了するまで、ユーザは表を更新することはできません。

  参考:
    Document 1706766.1(KROWN:22496) ANALYZE中のDML処理について

 表の検証、表に作成された索引の検証は、以下のように行います。

  SQL> analyze table <owner>.<table_name> validate structure;

   SQL> analyze index <owner>.<index_name> validate structure;

  パーティション表については Document 1703145.1(KROWN:13655) や  Note 111990.1 をご確認くだ
  さい。

  参考:
    Document 1703145.1(KROWN:13655) パーティション表の検査のために analyze を実行すると 
    ORA-14508 が発生する

 4-1. "VALIDATE"にエラーが返る場合は表が破損していますので、最新の
   バックアップからリカバリする必要があります。

 4-2. ORA-1410 が発生せずにテーブル・フルスキャンができる場合、テーブ
   ルの再作成( export/import ユーティリティの利用、create table as 
   select による再作成)を行います。

 4-3.索引の"VALIDATE" でエラーが返る場合は、索引を削除して再作成する
   必要があります。

 4-4.表とすべての索引の"VALIDATE"が問題なく行われる場合には、誤った 
   ROWID がメモリ上にキャッシュされた可能性があるため、共有プールの
   フラッシュによりクリアします。共有プールのフラッシュは、共有プール
   が通常の状態に戻るまで、一時的にパフォーマンスに影響を与える可能性
   があります。索引の ROWID がメモリ上で不正になっている場合にも、
   バッファキャッシュのフラッシュは有効ですが、索引がディスク上で破
   損している場合には、初めに索引を使用した時に ORA-1410 が再び返さ
   れます。

    SQL> alter system flush shared_pool;

 以上の対処を行っても ORA-1410 が発生し続ける場合、Oracle の不具合であ
 る可能性があります。詳細な調査を行うため、日本オラクルカスタマー
 サポートセンターにお問い合わせください。


[既知の問題]
Document 1738872.1(KROWN:124422) 2 億件以上のデータに対し、テキスト索引を作成した場合にエラー発生


[補足事項]
- ROWID の復号
 
 dbms_rowid パッケージの rowid_info プロシージャを使用して ROWID を復号
 することができます。以下は、PL/SQL 無名ブロックを用いて ROWID を復号
 した例です。

    例:

    SQL> set serveroutput on
    SQL> declare 
           my_rowid rowid := 'AAAR6tAAEAAAACeAAA'; 
                                     -- 復号する ROWID を指定
           rowid_type number;
           object_number number; 
           relative_fno number; 
           block_number number; 
           row_number number; 
         begin 
           dbms_rowid.rowid_info(my_rowid, rowid_type, object_number, 
                              relative_fno, block_number, row_number); 
           dbms_output.put_line('ROWID:   ' || my_rowid); 
           dbms_output.put_line('Object#:      ' || object_number); 
           dbms_output.put_line('RelFile#:     ' || relative_fno); 
           dbms_output.put_line('Block#:       ' || block_number); 
           dbms_output.put_line('Row#:         ' || row_number); 
         end; 
        /
    ROWID:   AAAR6tAAEAAAACeAAA
    Object#:      73389
    RelFile#:     4
    Block#:       158
    Row#:         0

    PL/SQLプロシージャが正常に完了しました。

   -- オブジェクト名の検索 (オブジェクト番号:73389)
   SQL> col owner for a10
   SQL> col object_name for a30
   SQL> select owner,object_name,object_type,data_object_id 
        from dba_objects 
        where data_object_id = 73389;

    -- データファイル名の検索 (相対ファイル番号:4)
    SQL> select file_name
         from dba_data_files
         where file_id = 4;

- ORA-1410 を発生させる例

 ここでは ORA-1410 をさせる簡単な例について説明します。

 例:
  1.簡単な表を作成し、2行挿入する

   -- 簡単な表の作成
    SQL> create table tab1 (col1 varchar(2), col2 varchar2(2)) 
         > tablespace users;

    表が作成されました。

    -- 2 行追加、コミット
      SQL> insert into tab1 values('aa','11');

      1行が作成されました。
   
      SQL> insert into tab1 values('aa','22');

      1行が作成されました。

      SQL> commit;

    -- ROWID の表示
      SQL> select rowid from tab1;

      ROWID
      ------------------
      AAAR6tAAEAAAACeAAA
      AAAR6tAAEAAAACeAAB
      
  
   2.不正なスロット番号(ROWID の末尾3桁)を使用した検索
  
   ROWID の末尾3桁 はスロット番号を表します。スロット番号 のみ変更し、
   存在しない ROWID で検索をすると「レコードが選択されませんでした。」
   というメッセージが返されます。

    SQL> select * from tab1 where rowid = 'AAAR6tAAEAAAACeAAC';

      レコードが選択されませんでした。

  3.不正なブロック番号(ROWID の10-15桁目)を使用した検索
  
   ブロック番号を故意に不正なものに変更し、検索します。

    SQL> select * from tab1 where rowid = 'AAAR6tAAEFFFFCeAAC';
        select * from tab1 where rowid = 'AAAR6tAAEFFFFCeAAC'
                      *
        行1でエラーが発生しました。:
        ORA-01410: ROWIDが無効です。

   これは ROWID が破損した場合の例となります。

  4.オブジェクトの操作により正しい ROWID で ORA-1410 が発生する例
  
   この例では、表を TRUNCATE して、ROWID にどのような影響があるかを見ます。

   -- 表の ROWID を確認
   SQL> select rowid from tab1;
    
      ROWID
      ------------------
      AAAR6tAAEAAAACeAAA
      AAAR6tAAEAAAACeAAB

      -- rowid を使用して表のすべての列を検索
    SQL> select * from tab1 where rowid = 'AAAR6tAAEAAAACeAAA';

      CO CO
      -- --
      aa 11

      -- TRUNCATE TABLE
      SQL> truncate table tab1;

      表が切り捨てられました。

      -- 先ほどの SELECT文を使用し正しい ROWID で検索
    SQL> select * from tab1 where rowid = 'AAAR6jAAEAAAACPAAA';
      select * from tab1 where rowid = 'AAAR6jAAEAAAACPAAA'
                    *
      行1でエラーが発生しました。:
      ORA-01410: ROWIDが無効です。

   これは、よく発生する ORA-1410 の例です。SQL文は ROWID をメモリ上
   にキャッシュしていますが、表は切り捨てられており、表のすべての
   ブロックはなくなっています。キャッシュされた ROWID で検索すると、
   ORA-1410 が発生します。
   表パーティションを交換して非パーティション表にする時にも同じ現象
   が発生します。このケースではファイル番号が変わるため、メモリ上に
   キャッシュされたROWID を使用した SQL文にはすべて ORA-1410 が返さ
   れます。