Usage

このセクションでは、pglogical レプリケーション拡張機能の基本的な使用法について説明します。

クイックセットアップ

最初に、論理デコードをサポートするように PostgreSQL サーバーを適切に構成する必要があります。

wal_level = logical
max_worker_processes = 10   # one per database needed on provider node
                            # one per node needed on subscriber node
max_replication_slots = 10  # one per node needed on provider node
max_wal_senders = 10        # one per node needed on provider node
shared_preload_libraries = pglogical

PostgreSQL 9.5+ (これは 9.4 では機能しません) を使用していて、最後/最初の更新が優先される競合解決を処理したい場合 (

Conflicts を参照)、この追加オプションを postgresql.conf

に追加できます。

track_commit_timestamp = on # needed for last/first update wins conflict resolution
                            # property available in PostgreSQL 9.5+

pg_hba.conf は、localhost からの論理レプリケーション接続を許可する必要があります。 PostgreSQL 9.6 までは、論理レプリケーション接続は pg_hba.conf の replication キーワードを使用して管理されていました。 PostgreSQL 10 以降では、論理レプリケーション接続は、プロバイダー データベースへの通常の接続として pg_hba.conf によって処理されます。

次に、すべてのノードに pglogical 拡張機能をインストールする必要があります。

CREATE EXTENSION pglogical;

PostgreSQL 9.4 を使用している場合、pglogical_origin 拡張機能もそのノードにインストールする必要があります。

CREATE EXTENSION pglogical_origin;

次に、プロバイダー ノードを作成します。

SELECT pglogical.create_node(
    node_name := provider1,
    dsn := host=providerhost port=5432 dbname=db
);

public スキーマのすべてのテーブルを default レプリケーション セットに追加します。

SELECT pglogical.replication_set_add_all_tables(default, ARRAY[public]);

必要に応じて、追加のレプリケーション セットを作成し、それらにテーブルを追加することもできます ( 複製セット を参照)。

通常は、サブスクライブする前にレプリケーション セットを作成することをお勧めします。これにより、単一の初期トランザクションでの初期レプリケーション セットアップ中にすべてのテーブルが同期されます。ただし、大規模なデータベースのユーザーは、制御を強化するためにデータベースを段階的に作成することを希望する場合があります。

プロバイダー ノードがセットアップされると、サブスクライバーはそれをサブスクライブできます。まず、サブスクライバー ノードを作成する必要があります。

SELECT pglogical.create_node(
    node_name := subscriber1,
    dsn := host=thishost port=5432 dbname=db
);

最後に、サブスクライバー ノードで、バックグラウンドで同期とレプリケーション プロセスを開始するサブスクリプションを作成できます。

SELECT pglogical.create_subscription(
    subscription_name := subscription1,
    provider_dsn := host=providerhost port=5432 dbname=db
);

SELECT pglogical.wait_for_subscription_sync_complete(subscription1);

ベース バックアップを使用したサブスクライバ ノードの作成

SQLレベルのノードとサブスクリプションの作成に加えて、pglogical は、pg_basebackup でプロバイダーを複製し、それを pglogical サブスクライバーとして起動することで、サブスクライバーの作成もサポートします。これは pglogical_create_subscriber ツールで行われます。 --help の出力を参照してください。

pglogical.create_subscription のデータ同期オプションとは異なり、このクローンはレプリケーション セットを無視し、すべてのデータベースのすべてのテーブルをコピーします。ただし、特に高帯域幅のリンクでは、多くの場合、はるかに高速です。

ノード管理

ノードは、 SQLインターフェイスを使用して動的に追加および削除できます。

  • pglogical.create_node(node_name name, dsn text) ノードを作成します。

パラメーター:

1 node_name - 新しいノードの名前。データベースごとに 1 つのノードのみが許可されます。

パラメーター:

  • node_name - 既存のノードの名前

  • ifexists - true の場合、サブスクリプションが存在しない場合でもエラーはスローされません。デフォルトは false

  • pglogical.alter_node_add_interface(node_name name, interface_name name, dsn text) ノードに追加のインターフェイスを追加します。

ノードが作成されると、ノードと同じ名前で create_node で指定された dsn を使用して、そのためのインターフェイスも作成されます。このインターフェイスを使用すると、異なる接続文字列を持つ代替インターフェイスを既存のノードに追加できます。

パラメーター:

  • node_name - 既存のノードの名前

  • interface_name - 追加する新しいインターフェースの名前

  • dsn - 新しいインターフェイスに使用されるノードへの接続文字列

  • pglogical.alter_node_drop_interface(node_name name, interface_name name) ノードから既存のインターフェイスを削除します。

パラメーター:

  • node_name - 既存のノードの名前

  • interface_name - 既存のインターフェースの名前

サブスクリプション管理

pglogical.create_subscription(subscription_name name, provider_dsn text, replication_sets text[], synchronize_structure boolean, synchronize_data boolean, forward_origins text[], apply_delay interval) 現在のノードからプロバイダー ノードへのサブスクリプションを作成します。コマンドはブロックせず、アクションを開始するだけです。

パラメーター:

  • subscription_name - サブスクリプションの名前。一意でなければなりません

  • provider_dsn - プロバイダーへの接続文字列

  • replication_sets - サブスクライブするレプリケーション セットの配列。これらは既に存在している必要があります。デフォルトは “{default,default_insert_only,ddl_sql}” です。

  • synchronize_structure - プロバイダーからサブスクライバーに構造を同期するかどうかを指定します。デフォルトは false

  • synchronize_data - プロバイダーからサブスクライバーにデータを同期するかどうかを指定します。デフォルトは true

  • forward_origins - 転送する元の名前の配列。現在サポートされている値のみが空の配列であり、プロバイダー ノードで発生していない変更を転送しないことを意味します (これは、ノード間の双方向のレプリケーションに役立ちます)、または “{all }” は、変更元が何であれ、すべての変更を複製することを意味します。デフォルトは “{all}” です。

  • apply_delay - レプリケーションをどれだけ遅らせるか、デフォルトは 0 秒

  • force_text_transfer - テキスト表現を使用してすべての列をレプリケートするようプロバイダーに強制します (遅くなりますが、サブスクライバーでレプリケートされた列のタイプを変更するために使用される場合があります)。デフォルトは false

subscription_name は、レプリケーション接続によって application_name として使用されます。これは、pg_stat_replication 監視ビューに表示されることを意味します。 pglogical が Synchronous Replication セットアップの一部として使用される場合、synchronous_standby_names でも使用できます。

pglogical.wait_for_subscription_sync_complete(sub_name) を使用して、サブスクリプションが非同期的にレプリケーションを開始し、必要なスキーマやデータの同期を完了するまで待機します。

  • pglogical.drop_subscription(subscription_name name, ifexists bool) サブスクリプションを切断し、カタログから削除します。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • ifexists - true の場合、サブスクリプションが存在しない場合でもエラーはスローされません。デフォルトは false

  • pglogical.alter_subscription_disable(subscription_name name, immediate bool) サブスクリプションを無効にし、プロバイダーから切断します。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • immediate - true の場合、サブスクリプションはすぐに停止されます。それ以外の場合は、現在のトランザクションの最後にのみ停止されます。デフォルトは false です。

  • pglogical.alter_subscription_enable(subscription_name name, immediate bool) 無効化されたサブスクリプションを有効にします。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • immediate - true の場合、サブスクリプションはすぐに開始されます。それ以外の場合は、現在のトランザクションの最後にのみ開始されます。デフォルトは false です。

  • pglogical.alter_subscription_interface(subscription_name name, interface_name name) 別のインターフェイスを使用してプロバイダー ノードに接続するようにサブスクリプションを切り替えます。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • interface_name - 現在のプロバイダー ノードの既存のインターフェイスの名前

  • pglogical.alter_subscription_synchronize(subscription_name name, truncate bool) すべてのセットのすべての非同期テーブルは、1 回の操作で同期されます。テーブルは 1 つずつコピーされ、同期されます。コマンドはブロックせず、アクションを開始するだけです。 pglogical.wait_for_subscription_sync_complete を使用して完了を待ちます。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • truncate - true の場合、テーブルはコピー前に切り捨てられます。デフォルトは false

  • pglogical.alter_subscription_resynchronize_table(subscription_name name,  relation regclass)

1 つの既存のテーブルを再同期します。テーブルは、外部キー制約のターゲットではない可能性があります。

ブロックせず、pglogical.wait_for_table_sync_complete を使用して完了を待ちます。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • relation - オプションで修飾された既存のテーブルの名前

pglogical.wait_for_subscription_sync_complete(subscription_name name)

サブスクリプションを待つか、pglogical.create_subscription または pglogical.alter_subscription_synchronize の後に同期を終了します。

この関数は、サブスクリプションの最初のスキーマ/データ同期があればそれが完了するまで待機し、個々の再同期を保留しているテーブルも同期を完了するまで待機します。

最良の結果を得るには、再同期を要求するレプリケーション セットの変更後にプロバイダーで SELECT pglogical.wait_slot_confirm_lsn(NULL, NULL) を実行し、その後でのみサブスクライバーで pglogical.wait_for_subscription_sync_complete を呼び出します。

pglogical.wait_for_table_sync_complete(subscription_name name, relation regclass)

pglogical.wait_for_subscription_sync_complete と同じですが、サブスクリプションの最初の同期と名前付きテーブルのみを待ちます。再同期を保留している他のテーブルは無視されます。

  • pglogical.wait_slot_confirm_lsn

SELECT pglogical.wait_slot_confirm_lsn(NULL, NULL)

現在のノードのすべてのレプリケーション スロットが、すべてのプロバイダーの呼び出し時に xlog 挿入位置まで再生されるまで待ちます。呼び出し時にすべてのスロットの confirmed_flush_lsn が pg_current_wal_insert_lsn() を通過すると戻ります。

必要に応じて、レプリケーション スロットを 1 つだけ待機することもできます (最初の引数)。オプションで、insert lsn (2 番目の引数) の代わりに任意の LSN が渡されるのを待つことができます。どちらも通常は null のままです。

この関数は、すべてのサブスクライバーがプロバイダーの特定のポイントまで変更を受信したことを確認するのに非常に役立ちます。

  • pglogical.show_subscription_status(subscription_name name) サブスクリプションに関するステータスと基本情報を表示します。

パラメーター:

subscription_name - 既存のサブスクリプションのオプションの名前。名前が指定されていない場合、関数はローカル ノード上のすべてのサブスクリプションのステータスを表示します

  • pglogical.show_subscription_table(subscription_name name, relation regclass)

テーブルの同期ステータスを表示します。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • relation - オプションで修飾された既存のテーブルの名前

  • pglogical.alter_subscription_add_replication_set(subscription_name name, replication_set name)

1 つの複製セットをサブスクライバーに追加します。同期せず、イベントの消費をアクティブ化するだけです。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • replication_set - 追加するレプリケーション セットの名前

  • pglogical.alter_subscription_remove_replication_set(subscription_name name, replication_set name) サブスクライバーから 1 つのレプリケーション セットを削除します。

パラメーター:

  • subscription_name - 既存のサブスクリプションの名前

  • replication_set - 削除するレプリケーション セットの名前

pglogical によって作成されたすべての接続に適用される接続オプションを割り当てるために設定できる postgresql.conf パラメータ、pglogical.extra_connection_options もあります。これは、カスタム キープアライブ オプションなどを設定するのに便利な場所です。

pglogical はデフォルトで TCP キープアライブを有効にして、アップストリーム サーバーが予期せず消えたときに確実に通知できるようにします。それらを無効にするには、keepalives = 0 を pglogical.extra_connection_options に追加します。

複製セット

レプリケーション セットは、データベース内のどのテーブルをレプリケートするか、およびそれらのテーブルでどのアクションをレプリケートするかを制御するメカニズムを提供します。

レプリケートされた各セットは、セットの INSERTs 、UPDATEs 、DELETEs 、および TRUNCATEs がレプリケートされるかどうかを個別に指定できます。すべてのテーブルを複数のレプリケーション セットに含めることができ、すべてのサブスクライバーも複数のレプリケーション セットにサブスクライブできます。レプリケートされたテーブルとアクションの結果のセットは、テーブルが含まれるセットの和集合です。テーブルは、レプリケーション セットに追加されるまでレプリケートされません。

「default」、「default_insert_only」、「ddl_sql」という名前の 3 つの既存のレプリケーション セットがあります。 「デフォルト」複製セットは、その中のテーブルに対するすべての変更を複製するように定義されています。 「default_insert_only」は INSERT のみを複製し、主キーを持たないテーブルを対象としています (詳細については、 Limitations and restrictions セクションを参照してください)。 「ddl_sql」レプリケーション セットは、pglogical.replicate_ddl_command で指定されたスキーマ変更をレプリケートするように定義されています。

複製セットを管理するために、次の機能が提供されています。

  • pglogical.create_replication_set(set_name name, replicate_insert bool, replicate_update bool, replicate_delete bool, replicate_truncate bool) この関数は、新しいレプリケーション セットを作成します。

パラメーター:

  • set_name - セットの名前、一意でなければなりません

  • replicate_insert - INSERT がレプリケートされるかどうかを指定します。デフォルトは true

  • replicate_update - UPDATE がレプリケートされるかどうかを指定します。デフォルトは true

  • replicate_delete - DELETE がレプリケートされるかどうかを指定します。デフォルトは true

  • replicate_truncate - TRUNCATE がレプリケートされるかどうかを指定します。デフォルトは true

  • pglogical.alter_replication_set(set_name name, replicate_inserts bool, replicate_updates bool, replicate_deletes bool, replicate_truncate bool) この関数は、既存のレプリケーション セットのパラメーターを変更します。

パラメーター:

  • set_name - 既存の複製セットの名前

  • replicate_insert - INSERT がレプリケートされるかどうかを指定します。デフォルトは true

  • replicate_update - UPDATE がレプリケートされるかどうかを指定します。デフォルトは true

  • replicate_delete - DELETE がレプリケートされるかどうかを指定します。デフォルトは true

  • replicate_truncate - TRUNCATE がレプリケートされるかどうかを指定します。デフォルトは true

  • pglogical.drop_replication_set(set_name text) レプリケーション セットを削除します。

パラメーター:

  • set_name - 既存の複製セットの名前

  • pglogical.replication_set_add_table(set_name name, relation regclass, synchronize_data boolean, columns text[], row_filter text) レプリケーション セットにテーブルを追加します。

パラメーター:

  • set_name - 既存のレプリケーション セットの名前

  • relation - セットに追加されるテーブルの名前または OID

  • synchronize_data - true の場合、テーブル データは、指定されたレプリケーション セットにサブスクライブされているすべてのサブスクライバーで同期されます。デフォルトは false

  • columns - 複製する列のリスト。通常、すべての列を複製する必要がある場合、これはデフォルトである NULL に設定されます。 警告:有効な行フィルターとデータを同期するときは注意してください。 有効な row_filter で synchronize_data=true を使用することは、テーブルに対する 1 回限りの操作のようなものです。変更された row_filter で再度実行すると、データはサブスクライバーに同期されません。サブスクライバーは、pglogical.alter_subscription_resynchronize_table() を呼び出して修正する必要がある場合があります。

  • pglogical.replication_set_add_all_tables(set_name name, schema_names text[], synchronize_data boolean) 指定されたスキーマにすべてのテーブルを追加します。既存のテーブルのみが追加され、今後作成されるテーブルは自動的に追加されません。今後作成されるテーブルが正しいレプリケーション セットに追加されるようにする方法については、 新しいテーブルのレプリケーション セットの自動割り当て を参照してください。

パラメーター:

  • set_name - 既存のレプリケーション セットの名前

  • schema_names - テーブルを追加する必要がある既存のスキーマの名前の配列

  • synchronize_data - true の場合、テーブル データは、指定されたレプリケーション セットにサブスクライブされているすべてのサブスクライバーで同期されます。デフォルトは false

  • pglogical.replication_set_remove_table(set_name name, relation regclass) レプリケーション セットからテーブルを削除します。

パラメーター:

  • set_name - 既存のレプリケーション セットの名前

  • relation - セットから削除するテーブルの名前または OID

  • pglogical.replication_set_add_sequence(set_name name, relation regclass, synchronize_data boolean) 複製セットにシーケンスを追加します。

パラメーター:

  • set_name - 既存のレプリケーション セットの名前

  • relation - セットに追加されるシーケンスの名前または OID

  • synchronize_data - true の場合、シーケンス値はすぐに同期されます。デフォルトは false

  • pglogical.replication_set_add_all_sequences(set_name name, schema_names text[], synchronize_data boolean) 指定されたスキーマからすべてのシーケンスを追加します。既存のシーケンスのみが追加され、将来作成されるシーケンスは自動的に追加されません。

パラメーター:

  • set_name - 既存のレプリケーション セットの名前

  • schema_names - テーブルを追加する既存のスキーマの名前の配列

  • synchronize_data - true の場合、シーケンス値はすぐに同期されます。デフォルトは false

  • pglogical.replication_set_remove_sequence(set_name name, relation regclass) 複製セットからシーケンスを削除します。

パラメーター:

  • set_name - 既存のレプリケーション セットの名前

  • relation - セットから削除されるシーケンスの名前または OID

pglogical.tables ビューをクエリすることで、どのテーブルがどのセットに含まれているかに関する情報を表示できます。

新しいテーブルのレプリケーション セットの自動割り当て

イベント トリガー機能は、新しく作成されたテーブルのレプリケーション セットを定義するルールを記述するために使用できます。

例:

CREATE OR REPLACE FUNCTION pglogical_assign_repset()
RETURNS event_trigger AS $$
DECLARE obj record;
BEGIN
    FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands()
    LOOP
        IF obj.object_type = table THEN
            IF obj.schema_name = config THEN
                PERFORM pglogical.replication_set_add_table(configuration, obj.objid);
            ELSIF NOT obj.in_extension THEN
                PERFORM pglogical.replication_set_add_table(default, obj.objid);
            END IF;
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

CREATE EVENT TRIGGER pglogical_assign_repset_trg
    ON ddl_command_end
    WHEN TAG IN (CREATE TABLE, CREATE TABLE AS)
    EXECUTE PROCEDURE pglogical_assign_repset();

上記の例では、スキーマ config で作成されたすべての新しいテーブルをレプリケーション セット configuration に配置し、拡張機能によって作成されていない他のすべての新しいテーブルは default レプリケーション セットに移動します。

追加機能

  • pglogical.replicate_ddl_command(command text, replication_sets text[]) ローカルで実行し、指定したコマンドをレプリケーション キューに送信して、指定した replication_sets のいずれかにサブスクライブしているサブスクライバーで実行します。

パラメーター:

  • command - 実行するDDLクエリ

  • replication_sets - このコマンドを関連付けるレプリケーション セットの配列、デフォルトは「{ddl_sql}」

  • pglogical.synchronize_sequence(relation regclass) シーケンス状態をすべてのサブスクライバーにプッシュします。サブスクリプションおよびテーブル同期関数とは異なり、この関数はプロバイダーで実行する必要があります。この関数が実行されたトランザクションをレプリケートすると、すべてのサブスクライバー (レプリケーション セットのフィルタリングは引き続き適用されます) によって消費される、追跡されたシーケンス状態の更新が強制されます。

パラメーター:

  • relation - オプションで修飾された既存のシーケンスの名前

行フィルタリング

PGLogical では、プロバイダ側とサブスクライバ側の両方で行ベースのフィルタリングが可能です。

プロバイダでの行フィルタリング

プロバイダーでは、pglogical.replication_set_add_table 関数に row_filter パラメーターを指定することで、行のフィルタリングを行うことができます。 row_filter は通常の PostgreSQL 式であり、CHECK 制約と同じ制限があります。

単純な row_filter は row_filter := 'id > 0' のようになります。これにより、id 列の値がゼロより大きい行のみが複製されます。

row_filter 内で volatile 関数を使用することは許可されていますが、書き込みを行う式はエラーをスローしてレプリケーションを停止するため、書き込みに関しては注意が必要です。

また、row_filter はレプリケーション セッション内で実行されているため、CURRENT_USER などのセッション固有の式には、書き込みを行ったセッションではなく、レプリケーション セッションの値が含まれることにも注意してください。

サブスクライバーでの行フィルタリング

サブスクライバでは、標準の BEFORE TRIGGER メカニズムを使用して、行ベースのフィルタリングを実装できます。

そのようなトリガーを ENABLE REPLICA または ENABLE ALWAYS としてマークする必要があります。そうしないと、レプリケーション プロセスによって実行されません。