2013年1月8日火曜日

スナップショットの罠【ORACLE】

こんにちは、大阪本社勤務のIです。

開発ブログということで、簡単ではありますが、
自分が開発時につまづいた内容などを投稿していきたいと思います。

現在、僕が携わっているシステムは、
メイン(仮にシステムAとします)のシステムがOracle10g、
サブ(仮にシステムBとします)のシステムがOracle8iで、
それぞれにデータベースが存在します。

また、システムA、システムBにて共通のテーブルがいくつかありますが、
夜間処理にて、システムAとシステムBの内容の同期をする仕組みになっています。

最近システムAで、あるテーブルのデータを日中に変更する必要があり、
システムAのデータを変更後、システムBに反映しようとしました。

手順としては、

①システムBのテーブルのデータを全件 DELETE する。

②データベースリンクを使用し、システムAのテーブルから SELECT し、
  システムBのテーブルに INSERT する。

…と考えていましたが、①を実行すると
「ORA-01732: このビューに対するデータ操作が無効です。」のエラーが出て、
データが削除できませんでした。

テーブルなのにビュー?…と思い、調べてみた結果、
システムBには、テーブル名と同名のスナップショットが存在していました。

□■□■□■□■□■ 調査メモ ■□■□■□■□■□
スナップショットとは、Oracleデータベース間で、データのバックアップを取る機能である。
スナップショットを作成すると、スナップショットと同名のテーブルが作成される。
そのテーブルに対して直接操作するには、スナップショットを作成する時に、
FOR UPDATE句を指定しないといけない。
スナップショットを同期するには下記のメソッドを使用。
DBMS_SNAPSHOT.REFRESH('スナップショット名','リフレッシュ方法')
リフレッシュ方法の内容
'F' ⇒ 高速リフレッシュ
'C' ⇒ 完全リフレッシュ
'?' ⇒ 強制リフレッシュ
'A' ⇒ 常にリフレッシュ
□■□■□■□■□■□■□■□■□■□■□■□■□

どうやらスナップショットが更新可能でなかったため、
DELETE 時にエラーが発生していたようです。

その後、当初考えていた手順ではなく、
DBMS_SNAPSHOT.REFRESH を実行することでテーブルの同期を行いました。

今回、スナップショットについて理解が乏しかったため、
このような現象に躓きましたが、良い勉強になりました。

この先、このようなことがあれば、投稿していきたいと思います。