Application behavior#
PGDのレプリケーション動作の多くは、アプリケーションに対して透過的です。 PGDでうまく動作するアプリケーションの開発を成功させるには、それを実現する方法と透明でない要素を理解することが重要です。
レプリケーション動作#
PGDは、あるノードで行われた変更の他のノードへの複製をサポートしています。
PGDは、デフォルトで、
INSERT、UPDATE、DELETE、およびTRUNCATE操作からのすべての変更をソースノードから他のノードにレプリケートします。すべてのトリガーとルールが処理された後、最終的な変更のみが送信されます。たとえば、
INSERT ... ON CONFLICT UPDATE
は、オリジンで発生した内容に応じて、挿入または更新を送信します。更新または削除が影響を与える行がない場合、変更は送信されません。
前提条件なしでINSERTをレプリケートできます。
他のノードで更新と削除をレプリケートするには、PGDが影響を受ける一意の行を識別できる必要があります。 PGDでは、テーブルにPRIMARY KEYが定義されている場合、UNIQUE制約、または特定の列に明示的なREPLICA IDENTITYが定義されていることが必要です。これらのいずれかが定義されていない場合、警告が生成され、その後の更新または削除は明示的にブロックされます。テーブルにREPLICA IDENTITY FULLが定義されている場合、一意のインデックスは必要ありません。その場合、更新と削除が許可され、ライブ、有効、遅延せず、式またはWHERE句を含まない最初の非一意のインデックスを使用します。それ以外の場合、シークエンシャル スキャンが使用されます。
Truncate#
TRUNCATEは、レプリケーションIDが定義されていない場合でも使用できます。 TRUNCATEコマンドのレプリケーションはサポートされていますが、外部キーで接続されたテーブルのグループを切り詰める場合には注意してください。 truncateアクションをレプリケートする場合、サブスクライバーは、レプリケーションセットが定義されている場合を除き、CASCADEによって明示的に指定または暗黙的に収集された、オリジンで切り詰められたテーブルのグループを切り捨てます。詳細と例については、
Replication sets を参照してください。これは、影響を受けるすべてのテーブルが同じサブスクリプションの一部である場合、正常に動作します。しかし、サブスクライバーで切り詰めるテーブルに、同じまたは任意のレプリケーションセットの一部ではないテーブルへの外部キーリンクがある場合、サブスクライバーにtruncateアクションを適用すると失敗します。
行レベルのロック#
INSERT、UPDATE、およびDELETEコマンドによって暗黙的に取得された行レベルのロックは、変更が発生すると複製されます。
INSERT、UPDATE、DELETE、およびTRUNCATEコマンドによって暗黙的に取得されたテーブルレベルのロックもレプリケートされます。ユーザーセッションによる明示的な行レベルのロックSELECT ... FOR UPDATE/FOR SHARE
はレプリケートされず、アドバイザリロックもレプリケートされません。
SERIALIZABLEモードで実行されているトランザクションによって格納されている情報は、他のノードにレプリケートされません。
SERIALAZABLEのトランザクション分離レベルがサポートされていますが、マルチプルのノードに同時トランザクションが存在する場合、トランザクションはノード全体でシリアル化されません。
- DMLがマルチプルのノードで同時に実行される場合、非同期レプリケーションで実行すると潜在的な競合が発生する可能性があります。これらに対処するか、回避する必要があります。
競合 で議論されているように、さまざまな回避メカニズムが可能です。
シークエンス#
- シーケンスには、
bdr.sequences で説明している特別な処理が必要です。これは、クラスターでは、ノードが競合する値を作成するのを避けるためにシーケンスをグローバルにする必要があるためです。グローバルシーケンスは、完全性を保証するグローバルロックで使用できます。
バイナリオブジェクト#
BYTEA列のバイナリデータは通常にレプリケートされ、最大1 GBのデータの「blob」が許可されます。 PostgreSQLの「ラージオブジェクト」機能の使用は、PGDではサポートされていません。
ルール#
ルールはオリジンノードでのみ実行されるため、レプリカに対して有効になっている場合でも、適用中に実行されません。
ベーステーブルのみ#
レプリケーションは、ベーステーブルからベーステーブルへのみ可能です。つまり、サブスクリプション側のソースとターゲットのテーブルは、ビュー、マテリアライズドビュー、外部テーブルではなく、テーブルである必要があります。ベーステーブル以外のテーブルを複製しようとすると、エラーが発生します。更新可能なビューを介して行われたDML変更は、オリジン上のベーステーブルに解決され、ターゲット上の同じベーステーブル名に適用されます。
パーティション化されたテーブル#
PGDは、パーティション化されたテーブルを透過的にサポートします。つまり、パーティション化されたテーブルをレプリケーションセットに追加でき、パーティションに関係する変更はダウンストリームにレプリケートされます。
トリガー#
デフォルトでは、トリガーは元のノードでのみ実行されます。たとえば、
INSERTトリガーは元のノードで実行され、ターゲットノードに変更を適用するときに無視されます。
ALTER TABLE ... ENABLE ALWAYS TRIGGER
を使用して、実行時にオリジンノードで実行され、レプリケートされたときにターゲットで実行されるトリガー「適用時」を指定できます。または、
REPLICA オプションを使用して適用時にのみ実行します
ALTER TABLE ... ENABLE REPLICA TRIGGER 。
一部のトリガーは、テーブルに存在し、現在有効になっている場合でも、適用時に実行されません。実行されないトリガータイプは次のとおりです。
ステートメントレベルのトリガー
FOR EACH STATEMENT列ごとのUPDATEトリガー
UPDATE OF column_name [, ...]
PGDレプリケーション適用は、システムレベルのデフォルトのsearch_pathを使用します。レプリカトリガー、ストリームトリガー、およびインデックス式ファンクションは、適用時に実行時に失敗する他のsearch_path設定を引き受けることができます。これの発生を防ぐには、次のいずれかのテクニックを使用します。
デフォルトのsearch_pathのみを使用して、オブジェクト参照を明確に解決します。
オブジェクトへの完全修飾参照は常に使用します
schema.objectnameなど。影響を受けるファンクションに対して
ALTER FUNCTION ... SET search_path = ...を使用して、ファンクションの検索パスを設定します。
PGDは、テキストまたはその他の照合可能なデータ型に関連する問題がないことを前提としています。つまり、使用中のすべての照合順序はすべてのノードで使用でき、デフォルトの照合順序はすべてのノードで同じです。変更のレプリケーションは、等価検索を使用してレプリカID値を見つけるため、一意のインデックスが一致しない照合修飾子で明示的に定義されている場合を除き、これは効果がありません。照合可能な式が使用される場合、行フィルタは照合順序の違いの影響を受ける可能性があります。
トースト#
PostgreSQLの非常に長い「トーストされた」データのPGD処理は、ユーザーに対して透過的です。 TOASTの「chunkid」値は、異なるノードの同じ行の間で異なる可能性がありますが、それは問題を発生させません。
その他の制限#
レプリカID列が外部としてマークされている場合、PGDは正しく動作できません。
PostgreSQLでは、揮発性ファンクションを含むCHECK()制約が許可されます。 PGDは適用時にCHECK()制約を再実行するため、以前と同じ結果を返さない後続の再実行はデータの相違を発生させます。
PGDは、外部キーの使用を制限しません。カスケードFKは許可されます。