読み取り専用インスタンス上にローカル論理レプリケーションスロットを作成することで、下流のサブスクライバーは読み取り専用インスタンスから変更を直接利用し、プライマリインスタンスの論理レプリケーション負荷をオフロードできます。
前提条件
お使いのインスタンスは PostgreSQL 16 以降で、かつマイナーカーネルバージョンが 20260530 以降である必要があります。インスタンスがこの機能をサポートしていない場合は、マイナーカーネルバージョンをアップグレードしてください。詳細については、「マイナーカーネルバージョンのアップグレード」をご参照ください。
背景情報
ネイティブの PostgreSQL では、論理レプリケーションスロットはプライマリインスタンスにのみ存在するため、下流のサブスクライバーは変更を利用するためにプライマリインスタンスに接続する必要があります。RDS PostgreSQL はこれを拡張し、読み取り専用インスタンス上のローカル論理レプリケーションスロットをサポートしています。これにより、サブスクライバーは代わりに読み取り専用インスタンスに接続し、プライマリインスタンスからレプリケーションのワークロードをオフロードできます。論理レプリケーションスロットの詳細については、「PostgreSQL の公式ドキュメント」をご参照ください。
注意事項
-
読み取り専用インスタンス上に作成された論理レプリケーションスロットは、ローカルスロットです。これはフェールオーバープロセスには含まれません。読み取り専用インスタンスが再構築された場合、スロットは失われ、再作成する必要があります。
-
この機能は、高可用性にとってクリティカルではない読み取り専用インスタンスでのみ使用してください。読み取り専用インスタンスが高可用性の読み取りトラフィックを処理している場合、スロットが失われると下流のサブスクリプションが中断される可能性があります。潜在的なビジネスへの影響を評価してください。
使用例
以下の例では、ストリーミングレプリケーションを介して同期されたプライマリインスタンス (RW) と読み取り専用インスタンス (RO) を使用し、3 つの典型的なユースケースを説明します。
-
基本的な使用法:
test_decodingプラグインを使用して、読み取り専用インスタンス上でスロットを手動で作成し、利用します。この方法は、カスタムのデコードロジックが必要なシナリオに適しています。 -
読み取り専用インスタンスへのサブスクリプション (自動スロット作成): これは最も一般的なユースケースで、
CREATE SUBSCRIPTIONコマンドが読み取り専用インスタンス上にスロットを自動的に作成します。 -
読み取り専用インスタンスへのサブスクリプション (手動でのスロット事前作成): これは、サブスクリプションを確立する前にスロットを手動で作成する高度なユースケースです。これにより、セットアッププロセス中に変更が失われないことが保証されます。
基本的な使用法:手動での作成と利用
読み取り専用インスタンス上に論理レプリケーションスロットを手動で作成し、test_decoding プラグインを使用してプライマリインスタンスからのデータ変更を利用します。
-
読み取り専用インスタンス上にローカル論理レプリケーションスロットを作成します。
-- [RO] ローカル論理レプリケーションスロットを作成します。 SELECT pg_create_logical_replication_slot('my_slot', 'test_decoding'); -
スロットが作成されたことを確認します。
-- [RO] スロットが作成されたことを確認します。 SELECT slot_name, plugin FROM pg_replication_slots WHERE slot_name = 'my_slot';出力例:
slot_name | plugin -----------+--------------- my_slot | test_decoding (1 row) -
プライマリインスタンスにデータを書き込みます。
-- [RW] プライマリインスタンスにデータを書き込みます。 INSERT INTO my_table VALUES (1), (2), (3); -
WAL が読み取り専用インスタンスでリプレイされるのを待ちます。
プライマリインスタンスで、現在の WAL LSN を照会します:
-- [RW] プライマリインスタンスで現在の WAL LSN を取得します。 SELECT pg_current_wal_lsn();読み取り専用インスタンスで、リプレイ LSN がプライマリインスタンスの WAL LSN 以上になるまでリプレイの進行状況を照会します:
-- [RO] 読み取り専用インスタンスのリプレイ進行状況を確認します。 SELECT pg_last_wal_replay_lsn();説明PostgreSQL 15 以降では、ポーリングの代わりに
pg_wal_replay_wait(target_lsn)関数を使用して、リプレイが特定の LSN に到達するのを待つこともできます。 -
読み取り専用インスタンスのスロットから変更を利用します。
-- [RO] スロットから変更を利用します。 SELECT * FROM pg_logical_slot_get_changes('my_slot', NULL, NULL);出力例:
lsn | xid | data -----------+-----+---------------------------------------- 0/XXXXXXX | 123 | table public.my_table: INSERT: ... (3 rows) -
スロットが不要になったら、削除します。
-- [RO] スロットを削除します。 SELECT pg_drop_replication_slot('my_slot');
自動スロット作成を伴うサブスクリプション
この一般的なユースケースでは、下流のサブスクライバーが読み取り専用インスタンスに直接接続し、CREATE SUBSCRIPTION コマンドがそのインスタンス上にスロットを自動的に作成します。
-
プライマリインスタンス上にテーブルとパブリケーションを作成します。
-- [RW] プライマリインスタンス上にテーブルとパブリケーションを作成します。 CREATE TABLE tab_rep (id int PRIMARY KEY, data text); CREATE PUBLICATION my_pub FOR TABLE tab_rep; -
WAL が読み取り専用インスタンスでリプレイされるのを待ち、パブリケーションが表示されることを確認します。手順については、「基本的な使用法」セクションの手順 4 をご参照ください。
-
下流のサブスクライバー上に同じテーブル構造を作成します。
-- [サブスクライバー] サブスクライバーインスタンス上にテーブル構造を作成します。 CREATE TABLE tab_rep (id int PRIMARY KEY, data text); -
下流のサブスクライバー上で、読み取り専用インスタンスに接続するサブスクリプションを作成します。
-- [サブスクライバー] 読み取り専用インスタンスに接続するサブスクリプションを作成します。 -- サブスクリプションは、読み取り専用インスタンス上に 'my_sub' という名前のスロットを自動的に作成します。 CREATE SUBSCRIPTION my_sub CONNECTION 'host=<RO_HOST> port=<RO_PORT> dbname=postgres' PUBLICATION my_pub WITH (copy_data = off);説明このアクションにより、読み取り専用インスタンス上に論理レプリケーションスロットが自動的に作成されます。このスロットは読み取り専用インスタンスに対してローカルであり、フェールオーバーには含まれず、インスタンスが再構築されると失われます。
-
プライマリインスタンスにデータを書き込み、同期を確認します。
-- [RW] プライマリインスタンスにデータを書き込みます。 INSERT INTO tab_rep VALUES (1, 'hello'), (2, 'world');データフロー:プライマリインスタンス → (ストリーミングレプリケーション / WAL) → 読み取り専用インスタンス → (論理レプリケーション) → 下流のサブスクライバー。
-- [サブスクライバー] データが同期されていることを確認します。 SELECT * FROM tab_rep;出力例:
id | data ----+------- 1 | hello 2 | world (2 rows) -
サブスクリプションが不要になったら、下流のサブスクライバーで削除します。このアクションにより、読み取り専用インスタンスからスロットが自動的に削除されます。
-- [サブスクライバー] サブスクリプションを削除します。これにより、読み取り専用インスタンス上のスロットが自動的に削除されます。 DROP SUBSCRIPTION my_sub;
手動でのスロット事前作成を伴うサブスクリプション
セットアップ中に変更が失われないように、サブスクリプションを確立する前にスロットを手動で事前作成できます。
-
読み取り専用インスタンス上にスロットを手動で作成します。
-- [RO] 読み取り専用インスタンス上にスロットを手動で作成します。 SELECT pg_create_logical_replication_slot('my_sub', 'pgoutput'); -
下流のサブスクライバー上で、既存のスロットを使用するサブスクリプションを作成します。
-- [サブスクライバー] サブスクリプションを作成し、既存のスロットを使用します。 CREATE SUBSCRIPTION my_sub CONNECTION 'host=<RO_HOST> port=<RO_PORT> dbname=postgres' PUBLICATION my_pub WITH (copy_data = off, create_slot = false);説明create_slot = falseを設定すると、CREATE SUBSCRIPTIONコマンドは、新しいスロットを作成する代わりに、読み取り専用インスタンス上の既存のスロットを使用します。以降の手順は、「自動スロット作成を伴うサブスクリプション」セクションと同じです。