私が持っている2つのデータベース(Oracle 10g)に関する質問がありました。それらをAとBと呼びましょう。Aは(さまざまなテーブルに)いくつかの情報を持っています。 Aの変更とBの「同期」。
Aに変更を加えることができない(選択するだけで、トリガーがない)ことを知って、いくつかの方法、手法、または多分考えについてお聞きしたいと思います。
あらかじめご理解とご協力をお願い申し上げます。
追加情報:
回答のおかげで、それが関連するかどうかはわかりませんが、「サブテーブル」(選択)で機能するかどうかはわかりませんが、MINUS演算子を見つけました。
"constantly check ... sync"および "Aに変更を加えることができない"という要件のため、オプションはかなり制限されています。マテリアライズドビューログ、dbms_alert、ストリーム、スタンバイデータベースなどはすべてテーブルから外れています。
Aのテーブルが常にすべての行を更新している場合(ジャックダグラスが言ったように)、マテリアライズドビューはセットアップが最も簡単です。ほとんどのレコードがAで時々変化しないというより可能性の高いイベントでは、Aから選択してBで必要に応じてマージおよび削除するパッケージをBでセットアップする必要があります。これにより、それが実行される頻度と同じくらい最新のものであるが、あなたの要件を考えると、それはあなたができる最善であるかもしれません。
具体的には、パッケージは次のことを行う必要があります。
Aのテーブルを複数回ヒットしないようにする場合は、テーブル全体をBのグローバル一時テーブルに挿入し、そこから削除/マージを実行できます。
マイナスについて:マイナス は、BにないAのクエリからのすべての行を示すことができます。 AのBマイナスクエリを使用すると、異なる行をすべて取得できますが、挿入/更新部分を追加する前であっても、処理に時間がかかる可能性があります。 Aが更新または削除を取得しない場合、最初のマイナスの結果を挿入できますが、insert into B...where not exists A...
の方が高速でシンプルです。
Aのテーブルが変更されたことを知るには、ポーリング以外の方法はありません。マテリアライズドビューを定期的に更新してdblinkで機能するようにすることもできますが、完全な更新しかできないため、テーブルが小さい場合にのみ実用的です。
難しいのは、db_AでSELECT以外のアクセス権がないことです。だからここに考えがありますが、それは満たすことができる(または満たされない)いくつかのかなり厳密な仮定が必要です:
要件:
ここで、db_Bで:
CREATE TABLE table1...
CREATE TABLE table2...,
etc.
PROCEDURE SYNC_TABLE1 IS
MAX_ACTIVITY_DATE DATE;
MAX_SEQUENCE_NO NUMBER;
BEGIN
SELECT MAX(SEQUENCE_NO), MAX(ACTIVITY_DATE)
INTO MAX_SEQUENCE_NO, MAX_ACTIVITY_DATE
FROM table1;
EXCEPTION WHEN NO_DATA_FOUND THEN
MAX_SEQUENCE_NO := 0;
MAX_ACTIVITY_DATE = TO_DATE('01/01/1980', 'MM/DD/YYYY');
END;
-- Bring over recent entries from db_A.table1 to db_B.table1
INSERT INTO table1
SELECT *
FROM table1@db_A
WHERE
-- if using timestamps as your criteria:
activity_date > MAX_ACTIVITY_DATE
-- if using sequence nos as your criteria:
sequence_no > MAX_SEQUENCE_NO
;
-- consider adding limiters to decrease the bandwidth necessary
-- for large transactions. For example activity_date < MAX_ACTIVITY_DATE + 30
-- would load a month's worth of transactions at a time. sequence_no <
-- MAX_SEQUENCE_NO + 500 would load 500 transactions at a time.
COMMIT;
EXCEPTION WHEN OTHERS THEN
ROLLBACK;
-- Consider logging the error!
RAISE;
END;
(lather, rinse, repeat.)
繰り返しますが、これは、連続する一意のID ORが常にdb_Aで更新されるアクティビティ日付である場合にのみ機能します(その日付は、以前のものなので、タイムスタンプが最適です。)
Oracleインスタンス間(およびOracle以外のインスタンス(OracleからmySqlなど))間でデータを同期する方法は、同期可能なすべてのテーブルにsync_date列があることを確認することです。データの同期が要求されると、sync_date列に同期の日付が入力されます。したがって、実際の同期プロセスは単純です。
FOR r in ( SELECT * FROM table1
WHERE sync_date IS NULL ) LOOP
send_sync_data_somewhere;
UPDATE table1
SET sync_date = current_timestamp
WHERE rowid=r.rowid;
END LOOP;
通常、リミッターが有効になりますが、あなたはそれを理解します。さらに、レコードのデータが変更された場合、sync_date列はNULLになり、その時点で同期プロセスは再びそれを取得します。
注:行が同期された後でデータの変更をサポートできる場合は、状況に関係なく、何らかの重複除外処理が必要になります。 UPDATE ... WHERE EXISTSと組み合わせたSELECT句でMERGEまたはWHERE NOT EXISTSを指定したINSERTを試すことができます。
うまくいけば、それが役立ちます。