Oracleエラー対応(ORA-12034):ORA-012034発生時の対処方法について

現役DBAが解説 ~Oracleエラー対応~

ORA-12034は、マテリアライズドビューの高速リフレッシュが失敗した際に発生するエラーです。

今回は、このORA-12034の概要とエラー原因および解決法を解説します。
また後半では、エラーが発生しないようにする予防手段についても紹介します。

1.エラーメッセージ

マテリアライズドビューで高速リフレッシュを行った際に、以下のようなエラーが発生する場合があります。

SQL> exec dbms_mview.refresh('TEST_MVIEW','f');
BEGIN dbms_mview.refresh('TEST_MVIEW','f'); END;

*
行1でエラーが発生しました。:
ORA-12034:
"USER2"."TEST_TABLE"のマテリアライズド・ビュー・ログは最終リフレッシュよりも新しいものです。
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行2960
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行2378
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行85
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行245
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行2360
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行2916
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行3199
ORA-06512: "SYS.DBMS_SNAPSHOT_KKXRCA", 行3229
ORA-06512: "SYS.DBMS_SNAPSHOT", 行15
ORA-06512: 行1

2.エラー原因

マテリアライズドビュー・ログに不整合が生じたため、エラーが発生しています。

マテリアライズドビュー・ログとは対象テーブルの差分更新を記録したもので、高速リフレッシュ時に使用されます。
マテリアライズドビュー・ログに不整合が発生する主な要因としては、元表に対するtruncateの実行が挙げられます。

例として、元表(TEST_TABLE)に対して、「delete+insert」を実施した場合と「truncate+insert」を実施した場合のマテリアライズドビュー・ログ(MLOG$_TEST_TABLE)のデータ件数を比較します。

●delete+insertの場合

SQL> --データ操作前
  SQL> select * from TEST_TABLE;

  ID NAME
---------- ----------
11111 a
22222 b
33333 c

SQL> select count(*) from MLOG$_TEST_TABLE;

COUNT(*)
----------
   1

SQL> --delete + insertを実施
SQL> delete from TEST_TABLE;

3 rows deleted.

SQL> insert into TEST_TABLE values (12345,'A');

1 row created.

SQL> insert into TEST_TABLE values (67890,'B');

1 row created.

SQL> commit;

Commit complete.

SQL> --データ操作後
SQL> select * from TEST_TABLE;

  ID NAME
---------- ----------
12345 A
67890 B

SQL> select count(*) from MLOG$_TEST_TABLE;

  COUNT(*)
----------
         6

truncate+insertの場合

SQL> --データ操作前
SQL> select * from TEST_TABLE;

        ID NAME
---------- ----------
      11111 a
      22222 b
      33333 c

SQL> select count(*) from MLOG$_TEST_TABLE;

  COUNT(*)
----------
          1

SQL> --truncate + insert を実施
SQL> truncate table TEST_TABLE;

Table truncated.

SQL> insert into TEST_TABLE values (12345,'A');

1 row created.

SQL> insert into TEST_TABLE values (67890,'B');

1 row created.

SQL> commit;

Commit complete.

SQL> --データ操作後
SQL> select * from TEST_TABLE;

        ID NAME
---------- ----------
      12345 A
      67890 B

SQL> select count(*) from MLOG$_TEST_TABLE;

  COUNT(*)
----------
         2

delete+insertの場合、もともと記録されていた1件 + delete3件 + insert2件 = 合計6件がマテリアライズドビュー・ログに記録されています。
これは実際のデータ操作とマテリアライズドビュー・ログとで整合性があるので高速リフレッシュを実行しても問題ありません。

しかし、truncate+insertの場合は、truncateが行われた時点でマテリアライズドビュー・ログの内容がリセットされてしまい、結果的にはtruncate後に実施したinsert2件のみがマテリアライズドビュー・ログに記録されています。
こちらは実際のデータ操作とマテリアライズドビュー・ログとで不整合が生じているので、高速リフレッシュを実行するとORA-12034のようなエラーが発生します。
このように、これまで問題なかった高速リフレッシュで突然ORA-12034が発生した場合は、前回のリフレッシュ以降にマテリアライズドビューの元表に対してtruncateを実行している可能性があります。
エラー調査を行う場合、まずは元表に対する何らかのデータメンテナンス作業が行われていないか確認してみることをおすすめします。

3.対処方法

本エラーの対処方法は、「手動での完全リフレッシュ」になります。
完全リフレッシュが実行されると、自動的にマテリアライズドビュー・ログの内容もリセットされ、正常に戻ります。
完全リフレッシュが成功すれば、次回からは高速リフレッシュが実行可能になります。

ただし、大規模なマテリアライズドビューの場合は完全リフレッシュに時間がかかり、DBパフォーマンスに影響が出る場合もあるため、実行タイミングには注意が必要です。

SQL> --完全リフレッシュを実行
SQL> exec dbms_mview.refresh('TEST_MVIEW','c');

PL/SQL procedure successfully completed.

4.事前エラー対策

そもそもORA-12034エラーを発生させないために、事前にできるエラー対策を紹介します。

4-1 データメンテナンス時の対応

「2. エラー原因」にも記載した通り、ORA-12034 は元表のtruncate作業後に発生することが多いです。
そのため、マテリアライズドビュー・ログが存在するテーブルに対してtruncateを伴うデータメンテナンスを行う場合は、メンテナンスの最後に関連するマテリアライズドビューの手動完全リフレッシュを実施しておけば、エラーを防ぐことができます。

4-2 マテリアライズドビューの設定変更

メンテナンスごとに毎回手動で完全リフレッシュを行うことが大変な場合は、マテリアライズドビューのデフォルトリフレッシュ方法を高速(FAST)ではなく、強制(FORCE)に変更するという手段もあります。
この強制とは、「基本は高速リフレッシュが実行されるが、実行できない場合は完全リフレッシュが実行される」というものです。
つまり、マテリアライズドビュー・ログに不整合が生じた場合は自動的に完全リフレッシュが実行されるようになるので、エラーが発生しなくなります。

ただし、大規模マテリアライズドビューにおいて強制にしてしまうと、「3. 対処方法」にも記載した通り、予期せず完全リフレッシュが自動実行されてしまい、その結果、パフォーマンスの低下など別のトラブルを招く可能性があります。
そのため、強制への変更は完全リフレッシュ実行時のシステムへの影響をよく確認した上で検討してください。

SQL> --リフレッシュ方法変更前
SQL> select mview_name, refresh_method from user_mviews  where mview_name ='TEST_MVIEW';

MVIEW_NAME      REFRESH_METHOD
--------------- ---------------
TEST_MVIEW      FAST

SQL> --デフォルトのリフレッシュ方法を高速→強制に変更
SQL> ALTER MATERIALIZED VIEW TEST_MVIEW REFRESH FORCE;

マテリアライズド・ビューが変更されました。

SQL> --リフレッシュ方法変更後確認
SQL> select mview_name, refresh_method from user_mviews  where mview_name ='TEST_MVIEW';

MVIEW_NAME      REFRESH_METHOD
--------------- ---------------
TEST_MVIEW      FORCE

5.最後に

ORA-12034は、マテリアライズドビューの高速リフレッシュ失敗時に発生するエラーです。
エラーの要因は元表へのtruncate実行によるものが多いため、元表のデータメンテナンスを行う際はよく確認をしておきましょう。