サブスクライバーノードでローカルにデータが変更された場合でも、データが更新されるという点では、論理レプリケーションは通常のDML操作と同じように振る舞います。
到着したデータが制約に違反すると、レプリケーションは停止します。
これは、コンフリクトと呼ばれます。
UPDATE
あるいはDELETE
操作をレプリケーションする場合は、存在しないデータによってコンフリクトは起こらず、そのような操作は単にスキップされます。
論理レプリケーション操作は、サブスクリプションを所有するロールの権限を使用して実行されます。
ターゲットテーブルで権限が失敗すると、レプリケーション競合が発生します。
サブスクリプション所有者が適用されるターゲットテーブルで有効行レベルセキュリティになりますが、レプリケーションされているINSERT
、UPDATE
、DELETE
またはTRUNCATE
をポリシーが通常拒否するかどうかには関係ありません。
行レベルセキュリティに対するこの制限は、PostgreSQLの将来のバージョンで解除される可能性があります。
コンフリクトはエラーを生じさせ、レプリケーションを停止させます。 コンフリクトはユーザが手動で解消しなければなりません。 コンフリクトの詳細は、サブスクライバーのサーバーログに出力されます。
この問題を解決するには、データを変更するか、サブスクライバーに対する権限を変更して、既存の変更でコンフリクトしないようにするか、既存のトランザクションと競合するデータをスキップします。 コンフリクトよってエラーが発生した場合、レプリケーションは処理を続行せず、論理レプリケーションワーカーは次のようなメッセージをサブスクライバーのサーバーログに送信します。
ERROR: duplicate key value violates unique constraint "test_pkey" DETAIL: Key (c)=(1) already exists. CONTEXT: processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 0/14C0378
制約とレプリケーションの起点名に違反する変更を含むトランザクションのLSNは、サーバーログ(LSN 0/14C0378とレプリケーション起点pg_16395
)から見つけることができます。
競合を発生させたトランザクションは、終了LSN(LSN 0/14C0378)でALTER SUBSCRIPTION ... SKIP
を使用してスキップできます。
終了LSNは、パブリッシャーでトランザクションがコミットまたは準備されたLSNにすることができます。
あるいは、pg_replication_origin_advance()
関数を呼び出して、トランザクションをスキップすることもできます。
この関数を使用する前に、ALTER SUBSCRIPTION ... DISABLE
を使用してサブスクリプションを一時的に無効にする必要があります。
また、サブスクリプションはdisable_on_error
オプションを使用して使用できます。
次に、pg_replication_origin_advance()
関数をnode_name
(pg_16395
)と終了LSNの次のLSN(0/14C0379)と共に使用できます。
現在の起点の位置は、pg_replication_origin_status
システムビューで確認できます。
トランザクション全体をスキップすることは、いかなる制約にも違反しない可能性のある変更をスキップすることを含むことに注意してください。
これは容易にサブスクライバーを不整合にする可能性があります。
streaming
モードがparallel
の場合、失敗したトランザクションの終了LSNはログに書き込まれないことがあります。
その場合、ストリーミングモードをon
またはoff
に変更し、再度同じコンフリクトを起こすことで、失敗したトランザクションの終了LSNをサーバのログに書き込むようにする必要があるかもしれません。
終了LSNの使用方法については、ALTER SUBSCRIPTION ... SKIP
を参照してください。