PostgreSQLで論理レプリケーションするテーブルを追加
はじめに
CREATE PUBLICATIONする時に「FOR ALL TABLES」を付与するとそれ以降CREATE TABLEしたテーブルは自動的にレプリケーション対象になると思い込んでいた。初歩的なのかもしれないがこの動作を知らなかったのでメモ。
結論を書くと「FOR ALL TABLES」を付与している場合でも「ALTER SUBSCRIPTION xxxxxxx REFRESH PUBLICATION」コマンドが必要となる。
事前確認
Publisher側の設定確認。All tablesがTrueになっている。
repdb=> \dRp+
Publication alltables
Owner | All tables | Inserts | Updates | Deletes
----------+------------+---------+---------+---------
postgres | t | t | t | t
(1 row)
Subscriber側の設定確認。logicalreplicationtestが既にレプリケーション対象となっている。
repdb=> SELECT
repdb-> a3.subname,
repdb-> a2.relname,
repdb-> a1.srsubstate,
repdb-> a1.srsublsn
repdb-> FROM
repdb-> pg_subscription_rel AS a1
repdb-> LEFT OUTER JOIN
repdb-> pg_class AS a2 ON
repdb-> a1.srrelid = a2.oid
repdb-> LEFT OUTER JOIN
repdb-> pg_stat_subscription AS a3 ON
repdb-> a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
--------------------+------------------------+------------+-----------
auroratopostgresql | logicalreplicationtest | r | 0/1220050
(1 row)
テーブルを追加
Publisher側、Subscriber側でテーブルを作成する。
repdb=> CREATE TABLE addtable1 (a int PRIMARY KEY);
CREATE TABLE
確認する。この時点でレプリケーション対象に追加されると思っていた。
repdb=> SELECT
repdb-> a3.subname,
repdb-> a2.relname,
repdb-> a1.srsubstate,
repdb-> a1.srsublsn
repdb-> FROM
repdb-> pg_subscription_rel AS a1
repdb-> LEFT OUTER JOIN
repdb-> pg_class AS a2 ON
repdb-> a1.srrelid = a2.oid
repdb-> LEFT OUTER JOIN
repdb-> pg_stat_subscription AS a3 ON
repdb-> a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
--------------------+------------------------+------------+-----------
auroratopostgresql | logicalreplicationtest | r | 0/1220050
(1 row)
repdb=>
ALTER SUBSCRIPTIONでREFRESHする。
repdb=> ALTER SUBSCRIPTION auroratopostgresql REFRESH PUBLICATION;
ALTER SUBSCRIPTION
ALTER SUBSCRIPTION https://www.postgresql.jp/document/10/html/sql-altersubscription.html
REFRESH PUBLICATION
不足しているテーブル情報をパブリッシャーから取得します。 最後のREFRESH PUBLICATION、あるいはCREATE SUBSCRIPTIONの実行の後でサブスクライブ対象のパブリケーションに追加されたテーブルの複製が、これにより開始されます。
ここでようやくレプリケーション対象が増えた。
repdb=> SELECT
repdb-> a3.subname,
repdb-> a2.relname,
repdb-> a1.srsubstate,
repdb-> a1.srsublsn
repdb-> FROM
repdb-> pg_subscription_rel AS a1
repdb-> LEFT OUTER JOIN
repdb-> pg_class AS a2 ON
repdb-> a1.srrelid = a2.oid
repdb-> LEFT OUTER JOIN
repdb-> pg_stat_subscription AS a3 ON
repdb-> a1.srsubid = a3.subid;
subname | relname | srsubstate | srsublsn
--------------------+------------------------+------------+-----------
auroratopostgresql | logicalreplicationtest | r | 0/1220050
auroratopostgresql | addtable1 | r | 0/5030740
(2 rows)
まとめ
CREATE PUBLICATION側のマニュアルには"そのデータベース内の全テーブルについての変更を複製するもの"という記載があるのでこれからテーブル追加時に自動的にレプリケーションされるものと思い込んでいた。
https://www.postgresql.jp/document/10/html/sql-createpublication.html
CREATE PUBLICATION FOR ALL TABLES そのパブリケーションでは、将来作成されるテーブルも含め、そのデータベース内の全テーブルについての変更を複製するものとして印をつけます。
レプリケーション対象のテーブルが増えたらALTER SUBSCRIPTION xxxxxxx REFRESH PUBLICATIONコマンドを実行しようという話。
関連しているかもしれない記事
- Aurora(PostgreSQL)とRDS(PostgreSQL)の環境で論理レプリケーションする
- PostgreSQL論理レプリケーションの遅延監視
- RDS(PostgreSQL)の論理レプリケーションの競合エラーを解消する
- RDS(PostgreSQL)でpg_replication_origin_statusにアクセス出来ない(permission denied)
- PostgreSQLのpg_dump、pg_restoreについてまとめる