Help us improve the AWS re:Post Knowledge Center by sharing your feedback in a brief survey. Your input can influence how we create and update our content to better support your AWS journey.
Amazon RDS for PostgreSQL DB インスタンス間で論理レプリケーションを使用してテーブルを複製する方法を教えてください。
Amazon Relational Database Service (Amazon RDS) for PostgreSQL DB インスタンス内の複数データベース間で、論理レプリケーションを使用してテーブルを複製したいと考えています。ただし、拡張機能の利用を避けたいです。
解決策
Amazon RDS for PostgreSQL は、PostgreSQL 10.4 以降での論理レプリケーションをサポートしています。Amazon Aurora PostgreSQL 互換エディションのバージョン 2.2.0 以降では、PostgreSQL 10.6 以降での論理レプリケーションがサポートされています。
詳細については、「Amazon RDS for PostgreSQL で論理レプリケーションを行う」を参照してください。
次の解決策では、2 つのソーステーブルを 2 つのターゲットテーブルに複製します。
論理レプリケーションを有効にする
次の手順を実行します。
- カスタムパラメータグループを作成し、rds.logical_replication パラメータを 1 に設定します。
注: rds.logical_replication は静的パラメータであるため、DB インスタンスを再起動する必要があります。DB インスタンスの再起動後、wal_level パラメータは logical に変更されます。 - パラメータグループを DB インスタンスに関連付けます。
- 次のクエリを実行し、wal_level が logical に設定されており、rds.logical_replication が有効であることを確認します。
想定される出力:SELECT name,setting FROM pg_settings WHERE name IN ('wal_level','rds.logical_replication');name | setting -------------------------+--------- rds.logical_replication | on wal_level | logical (2 rows)
ソーステーブルを作成し、データを挿入する
PostgreSQL DB インスタンスに接続し、ソースデータベースで次の手順を実行します。
-
次のコマンドを実行し、ソーステーブルを作成します。
CREATE TABLE reptab1 (slno int primary key); CREATE TABLE reptab2 (name varchar(20)); -
次のコマンドを実行し、ソーステーブルにデータを追加します。
INSERT INTO reptab1 VALUES (generate_series(1,1000)); INSERT INTO reptab2 SELECT SUBSTR ('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',((random()*(36-1)+1)::integer),1) FROM generate_series(1,50);
ソーステーブルのパブリケーションを作成する
ソースデータベースで次の手順を実行します。
-
次のコマンドを実行し、2 つのテーブルのパブリケーションを作成します。
CREATE PUBLICATION testpub FOR TABLE reptab1, reptab2; -
次のクエリを実行し、パブリケーションの詳細が適切であることを確認します。
SELECT * FROM pg_publication;想定される出力:
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate | pubviaroot --------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------ 115069 | testpub | 16395 | f | t | t | t | t | f (1 row) -
次のクエリを実行し、ソーステーブルがパブリケーションに含まれていることを確認します。
SELECT * FROM pg_publication;想定される出力:
pubname | schemaname | tablename ---------+------------+----------- testpub | public | reptab1 testpub | public | reptab2 (2 rows)
ターゲットデータベースに接続し、ターゲットテーブルを作成する
ターゲットデータベースで次の手順を実行します。
-
次のコマンドを実行し、ターゲットテーブルを作成します。
CREATE TABLE reptab1 (slno int primary key); CREATE TABLE reptab2 (name varchar(20));注: ソーステーブルと同じ名前を指定してください。
-
次のクエリを実行し、データがターゲットテーブルに含まれていないことを確認します。
テーブル 1:SELECT count(*) FROM reptab1;想定される出力:
count ------- 0 (1 row)テーブル 2:
SELECT count(*) FROM reptab2;想定される出力:
count ------- 0 (1 row)
ターゲットデータベースにサブスクリプションを作成する
サブスクリプションを作成する前に、次のコマンドを実行し、データベースログにはユーザー名とパスワードがプレーンテキストで保存されていないことを確認します。
SET log_min_messages to 'PANIC'; SET log_statement to NONE;
ターゲットデータベースにサブスクリプションを作成するには、次の手順を実行します。
-
サブスクリプションを作成するには、次のコマンドを実行します。
CREATE SUBSCRIPTION testsub CONNECTION 'host=source RDS/host endpoint port=5432 dbname=source_db_name user=user password=password' PUBLICATION testpub;注: source RDS/host endpoint をソース DB インスタンスのエンドポイントに、source_db_name を DB インスタンス名に置き換えてください。user をユーザー名に、password をパスワードに置き換えてください。
-
次のクエリを実行し、サブスクリプションがアクティブであることを確認します。
SELECT oid,subname,subenabled,subslotname,subpublications FROM pg_subscription;想定される出力:
oid | subname | subenabled | subslotname | subpublications -------+---------+------------+-------------+----------------- 16434 | testsub | t | testsub | {testpub} (1 row) -
次のクエリを実行し、データがターゲットテーブルに存在することを確認します。
テーブル 1:SELECT count(*) FROM reptab1;想定される出力:
count ------- 1000 (1 row)テーブル 2:
SELECT count(*) FROM reptab2;想定される出力:
count ------- 50 (1 row)
ソースデータベースのレプリケーションスロットに関する詳細を確認する
ターゲットデータベースでサブスクリプションを作成すると、ターゲットデータベースはソースデータベースにレプリケーションスロットを作成します。
レプリケーションスロットの詳細を確認するには、ソースデータベースで次のクエリを実行します。
SELECT * FROM pg_replication_slots;
想定される出力:
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size ----------+----------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+--------------- testsub | pgoutput | logical | 115048 | source | f | t | 846 | | 6945 | 58/B4000568 | 58/B40005A0 | reserved | (1 row)
ソーステーブルからのレプリケーションをテストする
ソースデータベースで次の手順を実行します。
-
次のコマンドを実行し、ソーステーブルに行を追加します。
INSERT INTO reptab1 VALUES(generate_series(1001,2000)); INSERT INTO reptab2 SELECT SUBSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',((random()*(36-1)+1)::integer),1) FROM generate_series(1,50); -
次のクエリを実行し、ソーステーブルのデータが変更されたことを確認します。
テーブル 1:SELECT count(*) FROM reptab1;想定される出力:
count ------- 2000 (1 row)テーブル 2:
SELECT count(*) FROM reptab2;想定される出力:
count ------- 100 (1 row)
ソーステーブルのデータがターゲットテーブルに複製されたことを確認する
ターゲットデータベースで次のクエリを実行し、ソーステーブルのデータがターゲットテーブルに複製されたことを確認します。
テーブル 1:
SELECT count(*) FROM reptab1;
想定される出力:
count ------- 2000 (1 row)
テーブル 2:
SELECT count(*) FROM reptab2;
想定される出力:
count ------- 100 (1 row)
レプリケーションスロットをクリアし、論理レプリケーションを無効にする
レプリケーションの完了後は、論理レプリケーションは必要ありません。スロットをクリアすると無効化されます。レプリケーションスロットが非アクティブの場合、Write-Ahead Logging (WAL) ファイルがソース DB インスタンスに蓄積されます。WAL ファイルによりストレージに空きがなくなり、ダウンタイムが引き起こされる可能性があります。
次の手順を実行します。
-
ターゲットデータベースで次のコマンドを実行し、サブスクリプションを削除します。
DROP SUBSCRIPTION testsub; -
ターゲットデータベースで次のクエリを実行し、サブスクリプションが削除されたことを確認します。
SELECT * FROM pg_subscription;想定される出力:
oid | subdbid | subname | subowner | subenabled | subconninfo | subslotname | subsynccommit | subpublications ----+---------+---------+----------+------------+-------------+-------------+---------------+----------------- (0 rows)注: ターゲットデータベースでサブスクリプションを削除すると、ターゲットデータベースはソースデータベースのレプリケーションスロットも削除します。
-
ソースデータベースで次のクエリを実行し、レプリケーションスロットがソースデータベースから削除されたことを確認します。
SELECT * FROM pg_replication_slots;想定される出力:
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size ----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+-------------- (0 rows) -
ソースデータベースで次のコマンドを実行し、パブリケーションを削除します。
DROP PUBLICATION testpub; -
ソースデータベースで次のクエリを実行し、パブリケーションが削除されたことを確認します。
SELECT * FROM pg_publication; SELECT * FROM pg_publication_tables;想定される出力:
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate | pubviaroot -----+---------+----------+--------------+-----------+-----------+-----------+-------------+------------ (0 rows) pubname | schemaname | tablename ---------+------------+----------- (0 rows) -
DB インスタンスのカスタムパラメータグループで rds.logical_replication パラメータを 0 に設定します。
注: DB インスタンスを再起動すると、変更が反映されます。 -
max_replication_slots、max_wal_senders、max_logical_replication_workers、max_worker_processes、max_sync_workers_per_subscription の各パラメータを使用状況に応じて確認します。
-
次のクエリを実行し、非アクティブなレプリケーションスロットの有無とスロットのサイズを確認します。
SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag, active FROM pg_replication_slots; -
(オプション) 次のコマンドを実行してレプリケーションスロットを削除します。
SELECT pg_drop_replication_slot('Your_slotname_name')
関連情報
レプリケーション (PostgreSQL のウェブサイト)
論理レプリケーション (PostgreSQL のウェブサイト)
