Replication sets

レプリケーションセットは、PGDノードがサブスクライブできるテーブルのグループです。レプリケーションセットを使用して、各ノードが他のノードの正確なコピーである通常の対称マルチマスターよりも複雑なレプリケーショントポロジを作成できます。

すべてのPGDグループは、グループと同じ名前の複製セットを作成します。このレプリケーションセットはデフォルトのレプリケーションセットであり、すべてのユーザーテーブルとDDLレプリケーションに使用されます。すべてのノードがサブスクライブしています。言い換えれば、デフォルトでは、すべてのユーザーテーブルがすべてのノード間で複製されます。

レプリケーションセットの使用

を使用して、挿入、更新、削除、または切り捨てのアクションを含めるかどうかを指定して、レプリケーションセットを作成できます。 1つのオプションでは既存のテーブルをセットに追加でき、2番目のオプションではテーブルの作成時にテーブルを追加するかどうかを定義します。

レプリケーションセットに追加または削除するテーブルを手動で定義することもできます。

レプリケーションセットに含まれるテーブルは、ノードがクラスターに参加したとき、およびその後に維持されます。

ノードが参加したら、レプリケーションセットからテーブルを削除できますが、再同期操作を使用して新しいテーブルを追加する必要があります。

デフォルトでは、新しく定義されたレプリケーションセットはDDLまたはPGD管理ファンクションコールをレプリケートしません。

bdr.replication_set_add_ddl_filter を使用

複製するコマンドを定義します。

PGDは、すべてのノードで複製セット定義を作成します。次に、 bdr.alter_node_replication_sets を使用して、各レプリケーションセットをパブリッシュまたはサブスクライブするように各ノードを定義できます。

関数を使用して、これらの定義を後で変更したり、複製セットを削除したりできます。

注釈

選択的複製にデフォルトの複製セットを使用しないでください。クラスター内のPGDノードでデフォルトのレプリケーションセットを削除または変更しないでください。デフォルトでDDLレプリケーションおよび管理ファンクション呼び出しにも使用されます。

パーティション分割テーブルの動作

PGDはパーティションテーブルを透過的にサポートします。つまり、パーティションテーブルをレプリケーションセットに追加できます。

いずれかのパーティションを含む変更は、ダウンストリームに複製されます。

注釈

パーティションがパーティションテーブルを介してレプリケートされる場合、パーティションで直接実行されるステートメントは、親テーブルで実行されるのと同じようにレプリケートされます。例外は`TRUNCATE` コマンドで、常に影響を受けるテーブルまたはパーティションのリストで複製されます。

個々のパーティションをレプリケーションセットに追加できます。その場合、それらは通常のテーブルのように、つまり、ダウンストリームのパーティションと同じ名前のテーブルに複製されます。パーティショニング定義がプロバイダーとサブスクライバーの両方で同じである場合、パーティショニングロジックを実行する必要がないため、この動作にはいくつかのパフォーマンス上の利点があります。

注釈

ルートパーティションテーブルがレプリケーションセットの一部である場合、個々のパーティションのメンバーシップは無視されます。そのルートテーブルのメンバーシップのみが考慮されます。

外部キーを使用した動作

外部キー制約は、参照元のテーブルの各行が参照先のテーブルの行と一致することを保証します。したがって、参照元のテーブルがレプリケーションセットのメンバーである場合、参照されるテーブルも同じレプリケーションセットのメンバーである必要があります。

PGDの現在のバージョンは、この条件を自動的にチェックまたは強制しません。レプリケーションセットにテーブルを追加するとき、データベース管理者は、外部キーによって参照されるすべてのテーブルも追加されることを確認する必要があります。

次のクエリを使用して、この要件を満たさないすべての外部キーとレプリケーションセットをリストできます。参照元のテーブルはレプリケーションセットのメンバーですが、参照先のテーブルはそうではありません。

SELECT t1.relname,
       t1.nspname,
       fk.conname,
       t1.set_name
  FROM bdr.tables AS t1
  JOIN pg_catalog.pg_constraint AS fk
    ON fk.conrelid = t1.relid
   AND fk.contype = f
 WHERE NOT EXISTS (
  SELECT *
    FROM bdr.tables AS t2
   WHERE t2.relid = fk.confrelid
     AND t2.set_name = t1.set_name
);

このクエリの出力は次のようになります。

 relname | nspname |  conname  | set_name
- --------+---------+-----------+----------
 t2      | public  | t2_x_fkey | s2
(1 row)

この出力は、テーブルt2 はレプリケーションセットs2 のメンバーですが、外部キーt2_x_fkey によって参照されるテーブルはそうではないことを意味します。

TRUNCATE CASCADE コマンドは、コマンドを複製する前に複製セットのメンバーシップを考慮します。例:

TRUNCATE table1 CASCADE;

これは、レプリケーションセットのみの一部であるすべてのテーブルでカスケードのないTRUNCATE になります。

TRUNCATE table1, referencing_table1, referencing_table2 ...

レプリケーションセットのメンバーシップ

1つ以上のレプリケーションセットにテーブルを追加したり、テーブルを削除したりできます。これを行うと、それらのテーブルの変更のみのレプリケーション(DML)に影響します。スキーマの変更(DDL)は、 DDLレプリケーションセットフィルターによって処理されます( DDL replication filtering を参照)。

レプリケーションは、ノードレプリケーションセット構成を持つレプリケーションセットのテーブルメンバーシップを使用して、どのノードにレプリケートするアクションを決定します。決定は、すべてのメンバーシップとレプリケーションセットオプションの和集合を使用して行われます。テーブルが、 INSERTアクションのみをレプリケートするレプリケーションセットAと、 UPDATEアクションのみをレプリケートするレプリケーションセットBのメンバーであるとします。ターゲットノードがレプリケーションセットAとBの両方にサブスクライブしている場合、 INSERT アクションと UPDATE アクションの両方がレプリケートされます。

を使用してメンバーシップを制御できます。

レプリケーションセットのリスト

次のクエリを使用して、既存のレプリケーションセットをリストできます。

SELECT set_name
FROM bdr.replication_sets;

このクエリを使用して、特定のレプリケーションセット内のすべてのテーブルをリストできます。

  SELECT nspname, relname
  FROM bdr.tables
  WHERE set_name = myrepset;

:ref:`外部キーを使用した動作 <外部キーを使用した動作>` は、参照先テーブルが参照元テーブルと同じレプリケーションセットに含まれていないすべての外部キーをリストするクエリを示しています。

次のSQLを使用して、現在のノードがパブリッシュおよびサブスクライブするレプリケーションセットを表示します。

SELECT node_id,
       node_name,
       pub_repsets,
       sub_repsets
  FROM bdr.local_node_summary;

このコードは、次のような出力を生成します。

  node_id   | node_name |    pub_repsets     |   sub_repsets
- -----------+-----------+----------------------------------------
 1834550102 | s01db01   | {bdrglobal,bdrs01} | {bdrglobal,bdrs01}
(1 row)

クラスター内のすべてのノードに対して同じクエリを実行するには、次のクエリを使用できます。このアプローチは、すべてのノードに関連付けられたレプリケーションセットを同時に取得します。

WITH node_repsets AS (
  SELECT jsonb_array_elements(
    bdr.run_on_all_nodes($$
        SELECT
          node_id,
          node_name,
          pub_repsets,
          sub_repsets
        FROM bdr.local_node_summary;
    $$)::jsonb
  ) AS j
)
SELECT j->response->command_tuples->0->>node_id AS node_id,
       j->response->command_tuples->0->>node_name AS node_name,
       j->response->command_tuples->0->>pub_repsets AS pub_repsets,
       j->response->command_tuples->0->>sub_repsets AS sub_repsets
FROM node_repsets;

これは、たとえば次のことを示しています。

  node_id   | node_name |    pub_repsets     |    sub_repsets
- -----------+-----------+----------------------------------------
 933864801  | s02db01   | {bdrglobal,bdrs02} | {bdrglobal,bdrs02}
 1834550102 | s01db01   | {bdrglobal,bdrs01} | {bdrglobal,bdrs01}
 3898940082 | s01db02   | {bdrglobal,bdrs01} | {bdrglobal,bdrs01}
 1102086297 | s02db02   | {bdrglobal,bdrs02} | {bdrglobal,bdrs02}
(4 rows)

DDLレプリケーションのフィルタリング

デフォルトでは、サポートされているすべてのDDLのレプリケーションは、デフォルトのPGDグループレプリケーションセットを介して行われます。このレプリケーションは、PGDグループと同じ名前のDDLフィルターを使用して実現されます。このフィルターは、PGDグループが作成されるときに、デフォルトのPGDグループレプリケーションセットに追加されます。

これを調整するには、既存のすべてのレプリケーションセットのDDLレプリケーションフィルターを変更します。これらのフィルターは、レプリケーションセットのテーブルメンバーシップとは無関係です。データの変更と同じように、各DDLステートメントは、複数のレプリケーションセットの複数のフィルターに一致した場合でも、1回だけレプリケートされます。

次のクエリを使用して、既存のDDLフィルターをリストできます。フィルターごとに、コマンドタグとロール名に適用される正規表現を示します。

  SELECT * FROM bdr.ddl_replication;

:ref:`bdr.replication_set_add_ddl_filter <bdr.replication_set_add_ddl_filter>` および :ref:`bdr.replication_set_remove_ddl_filter <bdr.replication_set_remove_ddl_filter>` を使用して、

DDLフィルターを操作できます。それらはDDL と見なされるため、 DDLレプリケーションとグローバルロックの対象となります。