RDS PostgreSQL は、読み取り専用インスタンスでのローカル論理レプリケーションスロットの作成をサポートしています。これにより、下流のサブスクライバーが読み取り専用インスタンスに直接接続して変更を取得できるため、プライマリインスタンスから論理レプリケーションの負荷をオフロードできます。
前提条件
インスタンスは 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 をご参照ください。
下流のサブスクライバーで同じテーブル構造を作成します。
-- [Subscriber] サブスクライバーインスタンスでテーブル構造を作成します。 CREATE TABLE tab_rep (id int PRIMARY KEY, data text);下流のサブスクライバーで、読み取り専用インスタンスに接続するサブスクリプションを作成します。
-- [Subscriber] 読み取り専用インスタンスに接続するサブスクリプションを作成します。 -- サブスクリプションは、読み取り専用インスタンスで '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) → 読み取り専用インスタンス → (論理レプリケーション) → 下流のサブスクライバー。
-- [Subscriber] データが同期されたことを確認します。 SELECT * FROM tab_rep;出力例:
id | data ----+------- 1 | hello 2 | world (2 rows)サブスクリプションが不要になったら、下流のサブスクライバーで削除します。この操作により、読み取り専用インスタンスからスロットが自動的に削除されます。
-- [Subscriber] サブスクリプションを削除します。これにより、読み取り専用インスタンスのスロットが自動的に削除されます。 DROP SUBSCRIPTION my_sub;
手動スロット事前作成によるサブスクリプション
サブスクリプションを確立する前にスロットを作成する必要がある場合 (たとえば、セットアップ中に変更が失われないようにする場合)、スロットを手動で事前作成できます。
読み取り専用インスタンスでスロットを手動で作成します。
-- [RO] 読み取り専用インスタンスでスロットを手動で作成します。 SELECT pg_create_logical_replication_slot('my_sub', 'pgoutput');下流のサブスクライバーで、既存のスロットを使用するサブスクリプションを作成します。
-- [Subscriber] サブスクリプションを作成し、既存のスロットを使用します。 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コマンドは新しいスロットを作成せず、読み取り専用インスタンス上の既存のスロットを使用します。以降の手順は、「読み取り専用インスタンスへのサブスクライブ (スロットの自動作成)」セクションと同じです。