pglogical を使用してインスタンス間でデータを同期する - Amazon Relational Database Service

pglogical を使用してインスタンス間でデータを同期する

現在利用可能なすべての RDS for PostgreSQL バージョンは、pglogical 拡張機能をサポートしています。pglogical 拡張は、バージョン 10 で PostgreSQL により導入された機能的に類似した論理レプリケーション機能よりも前のものです。詳細については、「Amazon RDS for PostgreSQL の論理レプリケーションの実行」を参照してください。

pglogical 拡張が、2 つ以上の 間の論理レプリケーションをサポートします。RDS for PostgreSQL DB インスタンス。また、異なる PostgreSQL バージョン間のレプリケーション、および RDS for PostgreSQL DB と Aurora PostgreSQL DB クラスターで実行されているデータベース間のレプリケーションもサポートしています。pglogical 拡張は、公開/サブスクライブモデルを使用して、テーブルやその他のオブジェクト (シーケンスなど) への変更をパブリッシャーからサブスクライバーに複製します。パブリッシャーノードからサブスクライバーノードに変更が確実に同期されるようにするには、レプリケーションスロットを使用し、次のように定義されます。

  • パブリッシャーノードは、他のノードにレプリケートされるデータのソースである RDS for PostgreSQL DB インスタンスです。パブリッシャーノードは、パブリケーションセットでレプリケートするテーブルを定義します。

  • サブスクライバーノードは、公開者から WAL の更新を受け取る RDS for PostgreSQL DB インスタンスです。サブスクライバーは、パブリッシャーに接続してデコードされた WAL データを取得するためのサブスクリプションを作成します。サブスクライバーがサブスクリプションを作成すると、パブリッシャーノードに複製スロットが作成されます。

pglogical 拡張の設定についての情報は、以下を参照してください。

pglogical 拡張の要件と制限

RDS for PostgreSQL の現在利用可能なすべてのリリースが pglogical 拡張機能をサポートしています。

パブリッシャーノードとサブスクライバーノードの両方を論理レプリケーション用に設定する必要があります。

サブスクライバーからパブリッシャーにレプリケートするテーブルは、名前とスキーマが同じである必要があります。これらのテーブルにも同じ列が含まれている必要があり、列は同じデータ型を使用する必要があります。パブリッシャーテーブルとサブスクライバーテーブルの両方に同じプライマリキーが必要です。一意の制約事項としては PRIMARY KEY のみを使用することをお勧めします。

サブスクライバーノードのテーブルには、CHECK 制約と NOT NULL 制約について、パブリッシャーノードのテーブルよりも許可度が高い制約を設定できます。

pglogical 拡張は、PostgreSQL (バージョン 10 以降) に組み込まれている論理レプリケーション機能ではサポートされていない双方向レプリケーションなどの機能を提供します。詳細については、「PostgreSQL bi-directional replication using pglogical」(pglogical を使用した PostgreSQL の双方向レプリケーション) を参照してください。

pglogical 拡張のセットアップ

RDS for PostgreSQL DB インスタンスpglogical 拡張機能を設定するには、RDS for PostgreSQL DB インスタンスのカスタム DB パラメータグループの共有ライブラリに pglogical を追加します。また、論理デコードをオンにするには、rds.logical_replication パラメータの値を 1 に設定する必要があります。最後に、データベースに拡張を作成します。これらのタスクには、AWS Management Console または AWS CLI を使用できます。

これらのタスクを実行するには、rds_superuser ロールとしてアクセス許可が必要です。

以下の手順では、 RDS for PostgreSQL DB インスタンスがカスタム DB パラメータグループに関連付けられていることを前提としています。カスタム DB パラメータグループの作成については、「「パラメータグループを使用する」 」を参照してください。

pglogical 拡張をセットアップするには
  1. AWS Management Console にサインインし、Amazon RDS コンソール (https://console.aws.amazon.com/rds/) を開きます。

  2. ナビゲーションペインで、 RDS for PostgreSQL DB インスタンスを選択します。

  3. [Configuration] (設定) タブを開きます。RDS for PostgreSQL DB インスタンス。インスタンスの詳細の中から、パラメータグループのリンクを見つけてください。

  4. リンクを選択して、に関連するカスタムパラメータを開きます。RDS for PostgreSQL DB インスタンス。

  5. パラメータ検索フィールドに、shared_pre を入力して shared_preload_libraries パラメータを検索します。

  6. プロパティ値にアクセスするには、[Edit parameters] (パラメータの編集) を選択します。

  7. [Values] (値) フィールドのリストに pglogical を追加します。値のリスト内の項目を区切るにはカンマを使用します。

    pglogical が追加された shared_preload_libraries パラメータの画像。
  8. rds.logical_replication パラメータを見つけて 1 に設定し、論理レプリケーションをオンにします。

  9. RDS for PostgreSQL DB インスタンス を再起動して、変更を有効にします。

  10. インスタンスが使用可能になったら、psql (または pgAdmin) を使用して RDS for PostgreSQL DB インスタンスに接続します。

    psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  11. pglogical が初期化されていることを確認するには、次のコマンドを実行します。

    SHOW shared_preload_libraries; shared_preload_libraries -------------------------- rdsutils,pglogical (1 row)
  12. 次のように、論理デコードを有効にする設定を確認します。

    SHOW wal_level; wal_level ----------- logical (1 row)
  13. 次のように拡張を作成します。

    CREATE EXTENSION pglogical; EXTENSION CREATED
  14. [Save changes] (変更を保存) をクリックします。

  15. Amazon RDS コンソール (https://console.aws.amazon.com/rds/) を開きます。

  16. データベースリストから RDS for PostgreSQL DB インスタンス を選択して選択し、アクションメニューから [Reboot] (再起動) を選択します。

pglogical 拡張のセットアップするには

AWS CLI を使用して pglogical を設定するには、次の手順に示すように、modify-db-parameter-group オペレーションを呼び出してカスタムパラメータグループの特定のパラメータを変更します。

  1. 次の AWS CLI コマンドを使用して shared_preload_libraries パラメータに pglogical を追加します。

    aws rds modify-db-parameter-group \ --db-parameter-group-name custom-param-group-name \ --parameters "ParameterName=shared_preload_libraries,ParameterValue=pglogical,ApplyMethod=pending-reboot" \ --region aws-region
  2. 次の AWS CLI コマンドを使用して rds.logical_replication1 に設定し、の論理デコード機能をオンにします。RDS for PostgreSQL DB インスタンス。

    aws rds modify-db-parameter-group \ --db-parameter-group-name custom-param-group-name \ --parameters "ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot" \ --region aws-region
  3. 次の AWS CLI コマンドを使用して RDS for PostgreSQL DB インスタンスを再起動し、pglogical ライブラリを初期化します。

    aws rds reboot-db-instance \ --db-instance-identifier your-instance \ --region aws-region
  4. インスタンスが使用可能になったら、psql を使用して RDS for PostgreSQL DB インスタンスに接続します。

    psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  5. 次のように拡張を作成します。

    CREATE EXTENSION pglogical; EXTENSION CREATED
  6. 次の AWS CLI コマンドを使用して、 RDS for PostgreSQL DB インスタンスを再起動します。

    aws rds reboot-db-instance \ --db-instance-identifier your-instance \ --region aws-region

RDS for PostgreSQL DB インスタンスに論理レプリケーションを設定する

以下の手順では、2 つの RDS for PostgreSQL DB インスタンス間で論理レプリケーションを開始する方法を示しています。これらのステップでは、ソース (パブリッシャー) とターゲット (サブスクライバー) の両方に、pglogical 拡張のセットアップ で説明されているように pglogical 拡張が設定されていることを前提としています。

パブリッシャーノードを作成し、複製するテーブルを定義するには

これらのステップは、別のノードに複製する 1 つ以上のテーブルがあるデータベースが RDS for PostgreSQL インスタンスにあることを前提としています。サブスクライバー上のパブリッシャーからテーブル構造を再作成する必要があるため、まず必要に応じてテーブル構造を取得します。そのためには、psq1 メタコマンド \d tablename を使用してサブスクライバーインスタンスに同じテーブルを作成します。次の手順では、デモンストレーションを目的として、パブリッシャー (ソース) でサンプルテーブルを作成します。

  1. psql を使用して、サブスクライバーのソースとして使用したいテーブルがあるインスタンスに接続します。

    psql --host=source-instance.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb

    複製する既存のテーブルがない場合は、次のようにサンプルテーブルを作成できます。

    1. 次の SQL ステートメントを使用してサンプルテーブルを作成します。

      CREATE TABLE docs_lab_table (a int PRIMARY KEY);
    2. 次の SQL ステートメントを使用して、生成されたデータをテーブルに入力します。

      INSERT INTO docs_lab_table VALUES (generate_series(1,5000)); INSERT 0 5000
    3. 次の SQL ステートメントを使用して、テーブルにデータが存在することを確認します。

      SELECT count(*) FROM docs_lab_table;
  2. 次のように、この RDS for PostgreSQL DB インスタンスをパブリッシャーノードとして指定します。

    SELECT pglogical.create_node( node_name := 'docs_lab_provider', dsn := 'host=source-instance.aws-region.rds.amazonaws.com port=5432 dbname=labdb'); create_node ------------- 3410995529 (1 row)
  3. 複製するテーブルをデフォルトのレプリケーションセットに追加します。レプリケーションセットの詳細については、pglogical ドキュメントの「Replication sets」(レプリケーションセット) を参照してください。

    SELECT pglogical.replication_set_add_table('default', 'docs_lab_table', 'true', NULL, NULL); replication_set_add_table --------------------------- t (1 row)

パブリッシャーノードの設定が完了しました。これで、パブリッシャーから更新を受け取るようにサブスクライバーノードを設定できます。

サブスクライバーノードを設定し、更新を受信するサブスクリプションを作成するには

これらのステップは、RDS for PostgreSQL DB インスタンスpglogical 拡張機能を使用してセットアップされていることを前提としています。詳細については、「pglogical 拡張のセットアップ」を参照してください。

  1. psql を使用して、パブリッシャーから更新を受け取るインスタンスに接続します。

    psql --host=target-instance.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. サブスクライバーの RDS for PostgreSQL DB インスタンスで、パブリッシャーに存在するのと同じテーブルを作成します。この例では、テーブルは docs_lab_table です。次に示すようにテーブルを作成できます。

    CREATE TABLE docs_lab_table (a int PRIMARY KEY);
  3. このテーブルが空であることを確認します。

    SELECT count(*) FROM docs_lab_table; count ------- 0 (1 row)
  4. 次のように、この RDS for PostgreSQL DB インスタンスをサブスクライバーノードとして指定します。

    SELECT pglogical.create_node( node_name := 'docs_lab_target', dsn := 'host=target-instance.aws-region.rds.amazonaws.com port=5432 sslmode=require dbname=labdb user=postgres password=********'); create_node ------------- 2182738256 (1 row)
  5. サブスクリプションを作成します。

    SELECT pglogical.create_subscription( subscription_name := 'docs_lab_subscription', provider_dsn := 'host=source-instance.aws-region.rds.amazonaws.com port=5432 sslmode=require dbname=labdb user=postgres password=*******', replication_sets := ARRAY['default'], synchronize_data := true, forward_origins := '{}' ); create_subscription --------------------- 1038357190 (1 row)

    このステップを完了すると、パブリッシャーのテーブルのデータが、サブスクライバーのテーブルに作成されます。このことを確認するには、次の SQL クエリを使用します。

    SELECT count(*) FROM docs_lab_table; count ------- 5000 (1 row)

これ以降、パブリッシャーのテーブルに加えられた変更は、サブスクライバーのテーブルにレプリケートされます。

メジャーアップグレード後の論理レプリケーションの再確立

論理レプリケーションのパブリッシャーノードとして設定されている RDS for PostgreSQL DB インスタンスのメジャーバージョンアップグレードを実行する前に、アクティブではないものを含め、すべてのレプリケーションスロットを削除する必要があります。パブリッシャーノードからデータベーストランザクションを一時的に迂回させ、レプリケーションスロットを削除し、RDS for PostgreSQL DB インスタンスをアップグレードしてから、レプリケーションを再確立して再開することをお勧めします。

レプリケーションスロットはパブリッシャーノードでのみホストされます。論理レプリケーションシナリオの RDS for PostgreSQL サブスクライバーノードには削除するスロットはありませんが、パブリッシャーへのサブスクリプションを持つサブスクライバーノードとして指定されている間は、メジャーバージョンにアップグレードできません。RDS for PostgreSQL サブスクライバーノードをアップグレードする前に、サブスクリプションとノードを削除してください。詳細については、「RDS for PostgreSQL 用ロジカルレプリケーションスロットの管理」を参照してください。

論理レプリケーションが中断されたことの確認

次のように、パブリッシャーノードまたはサブスクライバーノードのいずれかにクエリを実行することで、レプリケーションプロセスが中断されたことを確認できます。

パブリッシャーノードを確認するには
  • psql を使用してパブリッシャーノードに接続して、pg_replication_slots 関数をクエリします。active 列の値に注目します。通常は t (true) が返されます。これは、レプリケーションがアクティブであることを示します。クエリがf (false) を返す場合は、サブスクライバーへのレプリケーションが停止したことを示します。

    SELECT slot_name,plugin,slot_type,active FROM pg_replication_slots; slot_name | plugin | slot_type | active -------------------------------------------+------------------+-----------+-------- pgl_labdb_docs_labcb4fa94_docs_lab3de412c | pglogical_output | logical | f (1 row)
サブスクライバーノードを確認するには

サブスクライバーノードでは、3 つの異なる方法でレプリケーションのステータスを確認できます。

  • サブスクライバーノードの PostgreSQL ログを調べて、失敗のメッセージを見つけます。ログでは、次に示すように、終了コード 1 を含むメッセージで失敗が識別されます。

    2022-07-06 16:17:03 UTC::@:[7361]:LOG: background worker "pglogical apply 16404:2880255011" (PID 14610) exited with exit code 1 2022-07-06 16:19:44 UTC::@:[7361]:LOG: background worker "pglogical apply 16404:2880255011" (PID 21783) exited with exit code 1
  • pg_replication_origin 関数をクエリします。次のように、psql を使用してサブスクライバーノード上のデータベースに接続し、pg_replication_origin 関数をクエリします。

    SELECT * FROM pg_replication_origin; roident | roname ---------+-------- (0 rows)

    結果セットが空の場合は、レプリケーションが中断されたことを意味します。通常、次のような出力が表示されます。

    roident | roname ---------+---------------------------------------------------- 1 | pgl_labdb_docs_labcb4fa94_docs_lab3de412c (1 row)
  • 次の例に示すように、pglogical.show_subscription_status 関数をクエリします。

    SELECT subscription_name,status,slot_name FROM pglogical.show_subscription_status(); subscription_name | status | slot_name ---====----------------+--------+------------------------------------- docs_lab_subscription | down | pgl_labdb_docs_labcb4fa94_docs_lab3de412c (1 row)

    この出力は、レプリケーションが中断されたことを示しています。そのステータスは down です。通常、出力にはステータスが replicating として表示されます。

論理レプリケーションプロセスが中断された場合は、次のステップに従ってレプリケーションを再確立できます。

パブリッシャーノードとサブスクライバーノード間の論理レプリケーションを再確立するには

レプリケーションを再確立するには、以下のステップで説明するように、まずサブスクライバーをパブリッシャーノードから切断し、次にサブスクリプションを再確立します。

  1. 次のように psql を使用してサブスクライバーノードに接続します。

    psql --host=222222222222.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. pglogical.alter_subscription_disable 関数を使用してサブスクリプションを非アクティブ化します。

    SELECT pglogical.alter_subscription_disable('docs_lab_subscription',true); alter_subscription_disable ---------------------------- t (1 row)
  3. 以下のように、pg_replication_origin をクエリして、パブリッシャーノードの識別子を取得します。

    SELECT * FROM pg_replication_origin; roident | roname ---------+------------------------------------- 1 | pgl_labdb_docs_labcb4fa94_docs_lab3de412c (1 row)
  4. 前のステップからの応答を pg_replication_origin_create コマンドに使用して、サブスクリプションが再確立されたときに使用できる識別子を割り当てます。

    SELECT pg_replication_origin_create('pgl_labdb_docs_labcb4fa94_docs_lab3de412c'); pg_replication_origin_create ------------------------------ 1 (1 row)
  5. 次の例のように、ステータスを true にして名前を渡し、サブスクリプションを有効にします。

    SELECT pglogical.alter_subscription_enable('docs_lab_subscription',true); alter_subscription_enable --------------------------- t (1 row)

ノードのステータスを確認します。ステータスはこの例のように replicating として表示されているはずです。

SELECT subscription_name,status,slot_name FROM pglogical.show_subscription_status(); subscription_name | status | slot_name -------------------------------+-------------+------------------------------------- docs_lab_subscription | replicating | pgl_labdb_docs_lab98f517b_docs_lab3de412c (1 row)

パブリッシャーノード上のサブスクライバーのレプリケーションスロットのステータスを確認します。スロットの active 列は t (true) を返し、レプリケーションが再確立されたことを示します。

SELECT slot_name,plugin,slot_type,active FROM pg_replication_slots; slot_name | plugin | slot_type | active -------------------------------------------+------------------+-----------+-------- pgl_labdb_docs_lab98f517b_docs_lab3de412c | pglogical_output | logical | t (1 row)

RDS for PostgreSQL 用ロジカルレプリケーションスロットの管理

論理レプリケーションシナリオでパブリッシャーノードとして機能している RDS for PostgreSQL DB インスタンスでメジャーバージョンアップグレードを実行する前に、インスタンスのレプリケーションスロットを削除する必要があります。メジャーバージョンアップグレードの事前確認プロセスにより、スロットが削除されるまでアップグレードを続行できないことが通知されます。

RDS for PostgreSQL DB インスタンスからスロットを削除するには、まずサブスクリプションを削除してからスロットを削除します。

pglogical 拡張を使用して作成されたレプリケーションスロットを特定するには、各データベースにログインしてノードの名前を取得します。サブスクライバーノードにクエリを実行すると、次の例に示すように、パブリッシャーノードとサブスクライバーノードの両方が出力されます。

SELECT * FROM pglogical.node; node_id | node_name ------------+------------------- 2182738256 | docs_lab_target 3410995529 | docs_lab_provider (2 rows)

次のクエリで、サブスクリプションの詳細を取得できます。

SELECT sub_name,sub_slot_name,sub_target FROM pglogical.subscription; sub_name | sub_slot_name | sub_target ----------+--------------------------------+------------ docs_lab_subscription | pgl_labdb_docs_labcb4fa94_docs_lab3de412c | 2182738256 (1 row)

これで、次のようにサブスクリプションを削除できます。

SELECT pglogical.drop_subscription(subscription_name := 'docs_lab_subscription'); drop_subscription ------------------- 1 (1 row)

サブスクリプションを削除すると、ノードを削除できます。

SELECT pglogical.drop_node(node_name := 'docs-lab-subscriber'); drop_node ----------- t (1 row)

次のように、ノードが存在しないことを確認できます。

SELECT * FROM pglogical.node; node_id | node_name ---------+----------- (0 rows)

pglogical 拡張のパラメータリファレンス

表には、pglogical 拡張に関連するパラメータがあります。pglogical.conflict_log_levelpglogical.conflict_resolution などのパラメータは、更新の競合を処理するために使用されます。パブリッシャーから変更をサブスクライブしているテーブルにローカルで変更を加えると、競合が発生する可能性があります。これ以外にも、競合は、双方向のレプリケーションや、複数のサブスクライバーが同じパブリッシャーからレプリケートする場合など、さまざまなシナリオで発生する可能性があります。詳細については、「PostgreSQL bi-directional replication using pglogical」(pglogical を使用した PostgreSQL の双方向レプリケーション) を参照してください。

パラメータ 説明

pglogical.batch_inserts

可能であれば、バッチ挿入。デフォルトでは設定されていません。オンにする場合は「1」に、オフにする場合は「0」に変更します。

pglogical.conflict_log_level

解決された競合のログ記録に使用するログレベルを設定します。サポートされている文字列値は、debug5、debug4、debug3、debug2、debug1、info、notice、warning、error、log、fatal、panic です。

pglogical.conflict_resolution

競合が解決可能な場合に競合を解決するために使用するメソッドを設定します。サポートされている文字列値は、error、apply_remote、keep_local、last_update_wins、first_update_wins です。

pglogical.extra_connection_options

すべてのピアノード接続に追加する接続オプション。

pglogical.synchronous_commit

pglogical 固有の同期コミット値

pglogical.use_spi

低レベル API の代わりに SPI (サーバープログラミングインターフェイス) を使用して変更を適用します。オンにする場合は「1」に、オフにする場合は「0」に設定します。SPI の詳細については、PostgreSQL ドキュメントの「サーバープログラミングインターフェイス」を参照してください。