Azure Database for PostgreSQL - フレキシブル サーバーでの論理レプリケーションと論理デコード

適用対象: Azure Database for PostgreSQL - フレキシブル サーバー

Azure Database for PostgreSQL フレキシブル サーバーでは、次の論理データ抽出とレプリケーションの手法がサポートされています。

  1. 論理レプリケーション

    1. データ オブジェクトをレプリケートする、PostgreSQL のネイティブ論理レプリケーションを使用する。 論理レプリケーションを使用すると、テーブル レベルのデータ レプリケーションなど、データ レプリケーションをきめ細かく制御できます。
    2. 論理ストリーミング レプリケーションと、データベースの初期スキーマのコピー、TRUNCATE のサポート、DDL のレプリケート機能など、より多くの機能を提供する pglogical拡張機能 使用します。
  2. 先書きログ (WAL) の内容をデコードすることで実施される論理デコード

論理レプリケーションと論理デコードを比較する

論理レプリケーションと論理デコードには、似ている点がいくつかあります。 両方とも:

2 つのテクノロジには次のような違いがあります。

論理レプリケーション:

  • レプリケートするテーブルまたはテーブルのセットを指定できます。

論理デコード:

  • データベース内のすべてのテーブルから変更を抽出します。

論理レプリケーションと論理デコードの前提条件

  1. ポータルの [サーバー パラメータ] ページに移動します。

  2. サーバー パラメーター wal_levellogical に設定します。

  3. pglogical 拡張機能を使用する場合は、 shared_preload_librariesazure.extensionsパラメータを検索し、 候補リスト ボックスから pglogical を選択します。

  4. max_worker_processes パラメーターの値を 16 以上に更新します。 そうしないと、 WARNING: out of background worker slotsなどのイシューが発生する可能性があります。

  5. 変更を保存し、サーバーを再起動して変更を適用します。

  6. Azure Database for PostgreSQL フレキシブル サーバー インスタンスで、接続しているリソースからのネットワーク トラフィックが許可されていることを確認します。

  7. 管理者ユーザーのレプリケーションのアクセス許可を付与します。

    ALTER ROLE <adminname> WITH REPLICATION;
    
  8. 使用しているロールに、レプリケートするスキーマに 特権があることを確認したい場合があります。 そうしないと、 Permission denied for schemaなどのエラーが発生する可能性があります。

Note

レプリケーション ユーザーを通常の管理者アカウントから分離することをお勧めします。

論理レプリケーションと論理デコードを使用する

ネイティブ論理レプリケーションを使用することは、Azure Database for PostgreSQL フレキシブル サーバーからデータをレプリケートする最も簡単な方法です。 SQL インターフェイスまたはストリーミング プロトコルを使用して、変更を使用できます。 SQL インターフェイスを使用して、論理デコードを使用して変更を使用することもできます。

ネイティブ論理レプリケーション

論理レプリケーションでは、"パブリッシャー" と "サブスクライバー" という用語を使用します。

  • パブリッシャーは、データを送信する Azure Database for PostgreSQL フレキシブル サーバー データベースです。
  • サブスクライバーは、データを送信する Azure Database for PostgreSQL フレキシブル サーバー データベースです。

論理レプリケーションを試すために使用できるサンプル コードを次に示します。

  1. パブリッシャー データベースに接続します。 テーブルを作成し、データをいくつか追加します。

    CREATE TABLE basic (id INTEGER NOT NULL PRIMARY KEY, a TEXT);
    INSERT INTO basic VALUES (1, 'apple');
    INSERT INTO basic VALUES (2, 'banana');
    
  2. テーブルのパブリケーションを作成します。

    CREATE PUBLICATION pub FOR TABLE basic;
    
  3. サブスクライバー データベースに接続します。 パブリッシャーと同じスキーマでテーブルを作成します。

    CREATE TABLE basic (id INTEGER NOT NULL PRIMARY KEY, a TEXT);
    
  4. 前に作成したパブリケーションに接続するサブスクリプションを作成します。

    CREATE SUBSCRIPTION sub CONNECTION 'host=<server>.postgres.database.azure.com user=<rep_user> dbname=<dbname> password=<password>' PUBLICATION pub;
    
  5. これで、サブスクライバーのテーブルに対してクエリを実行できるようになります。 発行元からデータを受信していることがわかります。

    SELECT * FROM basic;
    

    パブリッシャーのテーブルに行を追加し、サブスクライバーで変更を表示することができます。

    データを表示できない場合は、 azure_pg_admin のサインイン特権を有効にして、テーブルコンテンツを確認します。

    ALTER ROLE azure_pg_admin login;
    

論理レプリケーションの詳細については、PostgreSQL のドキュメントを参照してください。

同じサーバー上のデータベース間で論理レプリケーションを使用する

同じ Azure Database for PostgreSQL フレキシブル サーバー インスタンス上に存在する異なるデータベース間で論理レプリケーションを設定する場合は、現在存在する実装制限を回避するために、特定のガイドラインに従う必要があります。 現時点では、同じデータベース クラスターに接続するサブスクリプションの作成は、レプリケーション スロットが同じコマンド内に作成されていない場合にのみ成功します。それ以外の場合、 CREATE SUBSCRIPTION 呼び出しがLibPQWalReceiverReceive 待機イベントで、ハングします。 これは、Postgres エンジン内の既存の制限が原因で発生します。これは、今後のリリースで削除される可能性があります。

この制限を回避しながら、同じサーバー上の 「ソース」 データベースと 「ターゲット」 データベースの間で論理レプリケーションを効果的に設定するには、次に示すステップに従います:

最初に、ソース データベースとターゲット データベースの両方で同じスキーマを持つ "basic" という名前のテーブルを作成します。

-- Run this on both source and target databases
CREATE TABLE basic (id INTEGER NOT NULL PRIMARY KEY, a TEXT);

次に、ソース データベースでテーブルのパブリケーションを作成し、pg_create_logical_replication_slot 関数を使用して論理レプリケーション スロットを個別に作成します。これにより、スロットがサブスクリプションと同じコマンドで作成されたときに通常発生するハングの問題を回避できます。 pgoutput プラグインを使用する必要があります:

-- Run this on the source database
CREATE PUBLICATION pub FOR TABLE basic;
SELECT pg_create_logical_replication_slot('myslot', 'pgoutput');

その後、ターゲット データベースで、前に作成したパブリケーションのサブスクリプションを作成し、Azure Database for PostgreSQL フレキシブル サーバーが新しいスロットを作成できないように設定falseされていることを確認create_slotし、前の手順で作成したスロット名を正しく指定します。 コマンドを実行する前に、接続文字列のプレースホルダーを実際のデータベース資格情報に置き換えます。

-- Run this on the target database
CREATE SUBSCRIPTION sub
   CONNECTION 'dbname=<source dbname> host=<server>.postgres.database.azure.com port=5432 user=<rep_user> password=<password>'
   PUBLICATION pub
   WITH (create_slot = false, slot_name='myslot');

論理レプリケーションを設定したら、ソース データベースの "basic" テーブルに新しいレコードを挿入し、ターゲット データベースにレプリケートされることを確認することで今すぐそれをテストできます。

-- Run this on the source database
INSERT INTO basic SELECT 3, 'mango';

-- Run this on the target database
TABLE basic;

すべてが正しく構成されている場合は、ターゲット データベース内のソース データベースから新しいレコードを監視し、論理レプリケーションが正常に設定されたことを確認する必要があります。

pglogical 拡張機能

プロバイダー データベース サーバーとサブスクライバーで pglogical を構成する例を次に示します。 詳しくは、pglogical 拡張機能のドキュメントをご覧ください。 また、上で示した前提条件のタスクを実行してある必要があります。

  1. プロバイダーとサブスクライバー両方のデータベース サーバーのデータベースに、pglogical 拡張機能をインストールします。

    \c myDB
    CREATE EXTENSION pglogical;
    
  2. レプリケーション ユーザーがサーバー管理ユーザー (サーバーを作成したユーザー) 以外の場合は、ロール azure_pg_admin のメンバーシップをユーザーに付与し、そのユーザーに REPLICATION 属性と LOGIN 属性を割り当てるようにしてください。 詳しくは、pglogical のドキュメントをご覧ください。

    GRANT azure_pg_admin to myUser;
    ALTER ROLE myUser REPLICATION LOGIN;
    
  3. プロバイダー (ソースとパブリッシャー) のデータベース サーバーで、プロバイダー ノードを作成します。

    select pglogical.create_node( node_name := 'provider1',
    dsn := ' host=myProviderServer.postgres.database.azure.com port=5432 dbname=myDB user=myUser password=myPassword');
    
  4. レプリケーション セットを作成します。

    select pglogical.create_replication_set('myreplicationset');
    
  5. データベース内のすべてのテーブルをレプリケーション セットに追加します。

    SELECT pglogical.replication_set_add_all_tables('myreplicationset', '{public}'::text[]);
    

    別の方法として、特定のスキーマ (testUser など) から既定のレプリケーション セットにテーブルを追加することもできます。

    SELECT pglogical.replication_set_add_all_tables('default', ARRAY['testUser']);
    
  6. サブスクライバーのデータベース サーバーで、サブスクライバー ノードを作成します。

    select pglogical.create_node( node_name := 'subscriber1',
    dsn := ' host=mySubscriberServer.postgres.database.azure.com port=5432 dbname=myDB user=myUser password=myPasword' );
    
  7. サブスクリプションを作成して、同期とレプリケーションのプロセスを開始します。

    select pglogical.create_subscription (
    subscription_name := 'subscription1',
    replication_sets := array['myreplicationset'],
    provider_dsn := 'host=myProviderServer.postgres.database.azure.com port=5432 dbname=myDB user=myUser password=myPassword');
    
  8. その後、サブスクリプションの状態を確認できます。

    SELECT subscription_name, status FROM pglogical.show_subscription_status();
    

注意

pglogical では現在、DDL 自動レプリケーションはサポートされていません。 初期スキーマは、pg_dump --schema-only を使用して手動でコピーできます。 DDL ステートメントは、pglogical.replicate_ddl_command関数を使用してプロバイダーとサブスクライバーで同時に実行できます。 ここに記載されている、拡張機能のその他の制限事項に注意してください。

論理デコード

論理デコードは、ストリーミング プロトコルまたは SQL インターフェイスを介して使用できます。

ストリーミング プロトコル

多くの場合、ストリーミング プロトコルを使用して変更を行うことをお勧めします。 独自のコンシューマーやコネクタを作成したり、Debezium のようなサードパーティのサービスを使用したりできます。

pg_recvlogical によるストリーミング プロトコルの例については、wal2json のドキュメントを参照してください。

SQL インターフェイス

次の例では、SQL インターフェイスを wal2json プラグインと共に使用します。

  1. スロットを作成します。

    SELECT * FROM pg_create_logical_replication_slot('test_slot', 'wal2json');
    
  2. SQL コマンドを実行します。 次に例を示します。

    CREATE TABLE a_table (
       id varchar(40) NOT NULL,
       item varchar(40),
       PRIMARY KEY (id)
    );
    
    INSERT INTO a_table (id, item) VALUES ('id1', 'item1');
    DELETE FROM a_table WHERE id='id1';
    
  3. 変更を使用します。

    SELECT data FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'pretty-print', '1');
    

    出力は次のようになります。

    {
          "change": [
          ]
    }
    {
          "change": [
                   {
                            "kind": "insert",
                            "schema": "public",
                            "table": "a_table",
                            "columnnames": ["id", "item"],
                            "columntypes": ["character varying(40)", "character varying(40)"],
                            "columnvalues": ["id1", "item1"]
                   }
          ]
    }
    {
          "change": [
                   {
                            "kind": "delete",
                            "schema": "public",
                            "table": "a_table",
                            "oldkeys": {
                                  "keynames": ["id"],
                                  "keytypes": ["character varying(40)"],
                                  "keyvalues": ["id1"]
                            }
                   }
          ]
    }
    
  4. 使用が完了したら、スロットをドロップします。

    SELECT pg_drop_replication_slot('test_slot');
    

論理デコードの詳細については、PostgreSQL のドキュメントを参照してください。

モニター

論理デコードは監視する必要があります。 未使用のレプリケーション スロットはすべてドロップしてください。 変更が読み取られるまで、スロットには Postgres WAL ログおよび関連するシステム カタログが保持されます。 サブスクライバーまたはコンシューマーが失敗した場合、または適切に構成されていない場合は、ログが消費されないまま蓄積され、ストレージがいっぱいになります。 また、未使用のログによって、トランザクション ID の折り返しリスクが増加します。 どちらの状況でも、サーバーを使用できなくなる可能性があります。 そのため、論理レプリケーション スロットは継続的に使用する必要があります。 論理レプリケーション スロットが使用されなくなった場合は、すぐにドロップしてください。

pg_replication_slots ビューの 「アクティブ」 列は、コンシューマーがスロットに接続されているかどうかを示します。

SELECT * FROM pg_replication_slots;

Azure Database for PostgreSQL フレキシブル サーバーのフレキシブル サーバー メトリックを使用した最大使用トランザクション IDストレージにアラートを設定して、値が通常のしきい値を超えたときに通知します。

制限事項

  • こちらに記載されているように、論理レプリケーションの制限が適用されます。

  • スロットと HA フェールオーバー - Azure Database for PostgreSQL フレキシブル サーバーで高可用性 (HA) が有効なサーバーを使用する場合は、フェールオーバー イベント中に論理レプリケーション スロットが保持されないことに注意してください。 論理レプリケーション スロットを維持し、フェールオーバー後にデータの整合性を確保するには、PG フェールオーバー スロット拡張機能を使用することをお勧めします。 この拡張機能を有効にする方法の詳細については、 ドキュメントを参照してください。

重要

対応するサブスクライバーが存在しなくなった場合は、プライマリ サーバーの論理レプリケーション スロットを削除する必要があります。 それ以外の場合、WAL ファイルはプライマリに蓄積され、ストレージがいっぱいになります。 ストレージのしきい値が特定のしきい値を超え、論理レプリケーション スロットが使用されていないとします (サブスクライバーが使用できないため)。 その場合、Azure Database for PostgreSQL フレキシブル サーバー インスタンスは、その未使用の論理レプリケーション スロットを自動的に削除します。 このアクションにより、蓄積された WAL ファイルが解放され、ストレージがいっぱいになったためにサーバーが使用できなくなる状況を回避できます。