もしGoldenGateに、DBAやデータエンジニアが愛憎相半ばするパラメータがあるとすれば、HANDLECOLLISIONS
は間違いなくその筆頭に挙げられるでしょう。本番環境のReplicatプロセスがORA-00001: unique constraint violated
エラーで異常終了(Abend)し、データ同期が中断、ビジネスに緊急事態が発生します。この時、一見単純なHANDLECOLLISIONS
パラメータがプロセスを「生き返らせる」ことができますが、その代償は想像をはるかに超えるかもしれません。
本記事では、その動作原理を深く掘り下げ、様々なシナリオでの利点と欠点を分析し、明確な意思決定のフレームワークを提供します。読了後、いつ使用すべきか、いつ避けるべきかを自信を持って判断できるようになり、データの一貫性を保証するより良い代替手段を選択できるようになるでしょう。
1. 競合の根本原因:
ReplicatのABENDはあくまで症状に過ぎず、その背後には実際のデータ競合が存在します。
- INSERT 競合: Replicatがターゲットテーブルに行を挿入しようとしますが、同じ主キーまたは一意キーを持つ行が既に存在します。これは通常、データベースが
ORA-00001
(Oracle)または類似の一意性制約エラーをスローする原因となります。 - UPDATE 競合: Replicatが行を更新しようとしますが、主キーに基づいてターゲットテーブルでその行を見つけることができません。
- DELETE 競合: Replicatが行を削除しようとしますが、同様にターゲットテーブルでその行を見つけることができません。
Oracleでは、後の2つの状況は通常ORA-01403: no data found
エラーを引き起こし、ReplicatをAbendさせます。
では、これらの競合はどこから来るのでしょうか?私のプロジェクト経験に基づくと、根本原因は通常以下のいずれかです。
- 初期ロードと増分同期の「ギャップ」: これが最も一般的な原因です。expdp/impdp、RMAN、またはOGGなどのツールを使用して初期ロードを完了し、その後Extract/Replicatを起動して増分同期を行う際、増分キャプチャの開始点(CSN/LSN)が初期ロードのデータスナップショット点と完全に一致していない場合、この「ギャップ」または「重複」内のデータが競合を引き起こします。
- ターゲット側が「クリーン」でない: ターゲットデータベースは純粋な読み取り専用のレプリカではありません。他のアプリケーション、バッチジョブ、あるいはDBAの手動操作がターゲット側でデータを挿入、変更、または削除しており、ソース側とターゲット側のデータのミラー関係を破壊しています。
- 双方向またはActive-Activeレプリケーション: Active-Activeアーキテクチャでは、競合は設計上考慮すべき要素です。A側とB側が同時に同じ主キーを持つデータを挿入する可能性があります。これらの操作が相手側にレプリケートされると、必然的にINSERT競合が発生します。
- ソース側でのログに記録されない操作: 例えば、Oracleで
NOLOGGING
またはUNRECOVERABLE
オプション付きの操作を実行したり、TRUNCATE TABLE
コマンドを使用したりした場合(OGGはTRUNCATE
をサポートできますが、不適切な設定は問題を引き起こす可能性があります)。これらの操作はExtractプロセスによって完全にキャプチャされない可能性があり、ソース側とターゲット側の状態の不一致につながります。
これらの根本原因を理解すれば、Replicatに単にこれらのエラーを「無視」させることが根本的な問題を解決しないことがわかるでしょう。
2. HANDLECOLLISIONS
について
それでは、HANDLECOLLISIONS
について紹介します。Replicatパラメータファイルにこれを追加すると、前述の競合を処理するデフォルトの動作が変更されます。
動作原理
HANDLECOLLISIONS
のロジックは非常に直接的です。
- INSERT競合に遭遇した場合(ターゲットにレコードが既に存在する): プロセスをAbendさせる代わりに、この
INSERT
操作を強制的にUPDATE
操作に変換します。トレイルファイル内のレコードのすべての列値を使用して、ターゲットテーブル内の同じ主キーを持つ既存のレコードを上書きします。 - UPDATEまたはDELETE競合に遭遇した場合(ターゲットにレコードが存在しない): これもAbendさせません。代わりに、この
UPDATE
またはDELETE
操作を静かに無視(破棄)し、何事もなかったかのように次のレコードの処理に進みます。
重要なポイント: HANDLECOLLISIONS
の唯一の目的は、Replicatプロセスの継続性を保証することであり、データの絶対的な一貫性を保証するものではありません。それは「上書き」と「無視」という戦略を用いてエラーを回避し、データフローを継続させます。
潜在的なリスク
このメカニズムのリスクは明らかです。次のようなシナリオを考えてみましょう。
- ソース側:
UPDATE table SET status='A' WHERE id=1;
- ターゲット側: 何らかの理由で、id=1のレコードが誤って削除されました。
- Replicatがこの更新を適用しようとすると、「no data found」競合に遭遇します。
HANDLECOLLISIONS
が有効になっている場合、このUPDATE
操作は静かに破棄されます。- 結果: ソース側ではid=1のレコードの
status
は’A’ですが、ターゲット側ではそのレコード自体が存在しません。ここにデータ不整合が生まれ、OGGのどのレポートもこの「無視」イベントを通知しません。
3.HANDLECOLLISIONS
の正しい使い方
リスクは多いものの、特定のシナリオではHANDLECOLLISIONS
は依然として有効なツールです。以下に、OGG 19c/21cでそれを設定する方法を示します。
構文と例
HANDLECOLLISIONS
は、グローバルとテーブル固有の2つのレベルで設定できます。影響範囲を最小限に抑えるため、常にテーブルレベルの設定を優先することを強く推奨します。
誤った例:グローバル設定(非推奨)
-- rep01.prm
-- これはすべてのテーブルに適用されるため、リスクが非常に高く、推奨されない設定です
REPLICAT rep01
USERIDALIAS ogg_tgt DOMAIN OracleGoldenGate
HANDLECOLLISIONS
MAP sales.customers, TARGET sales.customers;
MAP sales.orders, TARGET sales.orders;
MAP hr.employees, TARGET hr.employees;
正しい例:テーブルレベル設定(推奨)
初期化段階でデータ不整合の可能性があることがわかっているsales.orders
テーブルに対してのみ競合を処理したいとします。
-- rep01.prm
-- これはリスクを既知のテーブルに限定する、より安全な設定です
REPLICAT rep01
USERIDALIAS ogg_tgt DOMAIN OracleGoldenGate
-- ordersテーブルに対して競合処理を有効にする
MAP sales.orders, TARGET sales.orders, HANDLECOLLISIONS;
-- 他のテーブルは有効にしない。いかなる競合もAbendを引き起こし、問題を迅速に検出できる
MAP sales.customers, TARGET sales.customers;
MAP hr.employees, TARGET hr.employees;
MAP
ステートメントに, HANDLECOLLISIONS
を追加することで、その適用範囲をsales.orders
テーブルに正確に限定します。customers
テーブルやemployees
テーブルでは、いかなる競合も通常通りAbendを引き起こします。これこそが我々が望むこと、つまり未知の問題を明らかにすることです。
図解:HANDLECOLLISIONS
のワークフロー
4. HANDLECOLLISIONS を使うべきとき、そしてより良い代替策
ここからが最も重要な部分です:果たして本当にこれを使うべきでしょうか?
HANDLECOLLISIONS
の合理的な使用シナリオ
- 一時的な問題解決: 本番のReplicatが予期せず停止し、ビジネスへの影響が大きく、短時間でデータの問題を特定・修正できない場合。一時的に
HANDLECOLLISIONS
を追加してプロセスを稼働させることができますが、必ず以下の条件を守ってください:- 問題のあるテーブルに対してのみ有効にする。
- 直ちにチケットを作成し、DBAまたはデータエンジニアに根本原因の調査を依頼する。
- 問題が解決したら、このパラメータを必ず削除する。
-
一回限りのデータ同期または移行: データ移行や新しい災害復旧データベースを構築する際、ソースとターゲット間に軽微な差異があることがわかっており、ビジネス要件としてソースを絶対的な正とする場合。
HANDLECOLLISIONS
を使用して強制的に上書きし、迅速にデータを整合させることができます。同期が安定したら、削除を検討すべきです。 - 双方向/Active-Activeアーキテクチャ: これが
HANDLECOLLISIONS
の最も正当な使用場面です。Active-Active環境では、競合は予期された動作です。それでも、HANDLECOLLISIONS
は競合検出・解決(CDR)メカニズムの一部に過ぎません。通常、「最終更新者が勝つ」ルールを保証したり、より複雑なビジネスロジックを実装したりするために、GETAPPLOPS
、USEMAX
などの他のパラメータやカスタムの競合解決ロジックと組み合わせる必要があり、単純に上書きするだけではありません。
より良い代替案:REPERROR
による精密な制御
単一方向レプリケーションのシナリオの大多数において、特定の、既知で、許容可能なエラーを無視したい場合、私はREPERROR
パラメータの使用をはるかに好みます。
REPERROR
は、特定のデータベースエラーコードに対して、具体的なアクション(ABEND
、DISCARD
、RETRY
など)を定義することができます。
** HANDLECOLLISIONS
vs. REPERROR
**
特徴 | HANDLECOLLISIONS |
REPERROR |
---|---|---|
粒度 | 粗粒度、固定の競合タイプを処理 | 細粒度、任意のデータベースエラーコードを対象可能 |
動作 | 固定:「InsertをUpdateに」、「Update/Deleteを無視」 | カスタマイズ可能なアクション(DISCARD 、ABEND 、RETRY ) |
透明性 | 動作は暗黙的で見落としやすい | エラー処理ルールはパラメータファイルで明示的 |
私のアドバイス | 上記の特定シナリオでのみ使用 | 本番の単一方向同期における推奨エラー処理ソリューション |
REPERROR
設定例
主キー競合(ORA-00001
)によるINSERTの失敗のみを無視し、「データが見つかりません」(ORA-01403
)エラーについては調査のためにプロセスをAbendさせたいとします。
-- rep01.prm
-- REPERROR を使用した精密な制御
REPLICAT rep01
USERIDALIAS ogg_tgt DOMAIN OracleGoldenGate
-- ORA-00001 エラーに遭遇した場合、操作を discard ファイルに記録して続行
REPERROR (1, DISCARD)
-- ORA-01403 エラーに遭遇した場合、デフォルトの動作(Abend)が実行される
-- (1403に対するルールが定義されていないため)
MAP sales.orders, TARGET sales.orders;
この設定はHANDLECOLLISIONS
よりもはるかに安全です。INSERT
をUPDATE
に変換しないため、意図しないデータの上書きを避けることができます。同時に、破棄されたすべての操作をdiscardファイルに記録するため、後で何が起こったかを確認できます。
まとめ
HANDLECOLLISIONS
は強力なツールですが、力が大きければリスクも大きくなります。最後に、チェックリストをまとめます。
- 一時的な問題ですか? -> 使う。ただし、対象は問題のあるテーブルのみに限定し、できるだけ早く削除する計画を立ててください。
- 一回限りのデータ整合を行っていますか? -> 検討の余地あり。完了後に削除してください。
- 双方向/Active-Active構成を設定していますか? -> 使う。ただし、唯一の解決策としてではなく、完全なCDR戦略の一部として使用すべきです。
- 通常の単一方向レプリケーション環境ですか? -> 使わない! 特定の既知のエラーを処理するには
REPERROR
を優先します。 - なぜ失敗するかわからず、ただプロセスを動かしたいだけですか? -> 絶対に使わない! それは問題を覆い隠しているだけです。まず根本原因を診断してください。
データ同期の核心は一貫性と信頼性です。プロセスの表面的な「継続的な実行」と引き換えにこれらを犠牲にする近道は、最終的にはより大きな代償を払うことになります。