【PostgreSQL 10/11】異なるメジャーバージョン間でのロジカルレプリケーションを検証してみた (その2)

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

今回は先日リリースされた PostgreSQL 11 を使って、異なるメジャーバージョン (PostgreSQL 10) との間でのロジカルレプリケーションを検証してみました。(※以下の内容は CentOS 7.5/PostgreSQL 10.5/PostgreSQL 11.0 にて検証しています。)

■はじめに

昨年リリースされた PostgreSQL 10 の新機能であるロジカルレプリケーションには “異なるメジャーバージョン間でレプリケーションが可能である” というメリットがあります。

前回は PostgreSQL 10 から PostgreSQL 11 へのロジカルレプリケーションを試してみましたが、今回は逆方向である PostgreSQL 11 から PostgreSQL 10 へのロジカルレプリケーションを試してみようと思います。

■検証 (環境構築)

それではさっそく、検証してみます。

今回は以下の様な構成で、PostgreSQL 11 から PostgreSQL 10 にデータをレプリケーションします。

[構成]
--------------------------------------------------
PostgreSQL 11 : Publisher (いわゆる Master)
PostgreSQL 10 : Subscriber (いわゆる Slave)
--------------------------------------------------

まず初めに、Publisher である PostgreSQL 11 にて “wal_level = logical” の設定を実施し、PostgreSQL 11 を起動します (他の設定は、基本的にデフォルト設定で動作するはずです)。また、既に PostgreSQL 11 が起動している場合は、wal_level の設定変更を反映させるために再起動が必要です。

[postgres@pgsqlv11 data]$ vim ./postgresql.conf 
[postgres@pgsqlv11 data]$ 
[postgres@pgsqlv11 data]$ grep wal_level ./postgresql.conf
#wal_level = replica                    # minimal, replica, or logical
wal_level = logical                     # minimal, replica, or logical
[postgres@pgsqlv11 data]$ 
[postgres@pgsqlv11 data]$ pg_ctl start
waiting for server to start....2018-11-07 08:05:21.196 UTC [1713] LOG:  00000: listening on IPv4 address
"0.0.0.0", port 5432
2018-11-07 08:05:21.196 UTC [1713] LOCATION:  StreamServerPort, pqcomm.c:593
2018-11-07 08:05:21.198 UTC [1713] LOG:  00000: listening on Unix socket "/tmp/.s.PGSQL.5432"
2018-11-07 08:05:21.198 UTC [1713] LOCATION:  StreamServerPort, pqcomm.c:587
2018-11-07 08:05:21.215 UTC [1713] LOG:  00000: redirecting log output to logging collector process
2018-11-07 08:05:21.215 UTC [1713] HINT:  Future log output will appear in directory "log".
2018-11-07 08:05:21.215 UTC [1713] LOCATION:  SysLogger_Start, syslogger.c:667
done
server started
[postgres@pgsqlv11 data]$ 
[postgres@pgsqlv11 data]$ psql
psql (11.0)
Type "help" for help.
postgres=# 
postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 11.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)

PostgreSQL 11 を起動したら、テスト用のテーブル “fuga” を作成し、適当なデータを INSERT します。

postgres=# CREATE TABLE fuga (a int primary key, b text);
CREATE TABLE
postgres=# 
postgres=# INSERT INTO fuga SELECT a, md5(clock_timestamp()::text) FROM generate_series(1,10) AS a;
INSERT 0 10
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
(10 rows)

次に Publisher として動作させるために PUBLICATION を作成します。作成した PUBLICATION に関する情報は、システムカタログの pg_publication や pg_publication_tables で確認することができます。これで PostgreSQL 11 側での設定は完了です。

postgres=# CREATE PUBLICATION fuga_pub FOR TABLE fuga;
CREATE PUBLICATION
postgres=# 
postgres=# SELECT * FROM pg_publication;
pubname  | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate 
----------+----------+--------------+-----------+-----------+-----------+-------------
fuga_pub |       10 | f            | t         | t         | t         | t
(1 row)
postgres=# 
postgres=# SELECT * FROM pg_publication_tables;
pubname  | schemaname | tablename 
----------+------------+-----------
fuga_pub | public     | fuga
(1 row)

次に Subscriber である PostgreSQL 10 側の構築を行います。こちらは、特にデフォルト値からの設定変更は行わずに起動します。

[postgres@pgsqlv10 data]$ pg_ctl start
waiting for server to start....2018-11-07 08:07:58.270 UTC [1707] LOG:  00000: listening on IPv4 address "0.0.0.0", port 5432
2018-11-07 08:07:58.270 UTC [1707] LOCATION:  StreamServerPort, pqcomm.c:593
2018-11-07 08:07:58.282 UTC [1707] LOG:  00000: listening on Unix socket "/tmp/.s.PGSQL.5432"
2018-11-07 08:07:58.282 UTC [1707] LOCATION:  StreamServerPort, pqcomm.c:587
2018-11-07 08:07:58.304 UTC [1707] LOG:  00000: redirecting log output to logging collector process
2018-11-07 08:07:58.304 UTC [1707] HINT:  Future log output will appear in directory "log".
2018-11-07 08:07:58.304 UTC [1707] LOCATION:  SysLogger_Start, syslogger.c:634
done
server started
[postgres@pgsqlv10 data]$ 
[postgres@pgsqlv10 data]$ psql
psql (10.5)
Type "help" for help.
postgres=# 
postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 10.5 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)

次に、レプリケーション対象のテーブル (Publisher である PostgreSQL 11 側で作成したテーブルと同じ定義のテーブル) を作成します。

postgres=# CREATE TABLE fuga (a int primary key, b text);
CREATE TABLE
postgres=# 
postgres=# SELECT * FROM fuga;
a | b 
---+---
(0 rows)

テーブルを作成したら、Subscriber として動作させるために SUBSCRIPTION を作成します。作成した SUBSCRIPTION に関する情報は、システムカタログの pg_subscription や pg_subscription_rel で確認することができます。

postgres=# CREATE SUBSCRIPTION fuga_sub CONNECTION 'host=pgsqlv11.example.com port=5432 user=postgres dbname=postgres' PUBLICATION fuga_pub;
NOTICE:  created replication slot "fuga_sub" on publisher
CREATE SUBSCRIPTION
postgres=# 
postgres=# SELECT * FROM pg_subscription;
subdbid | subname  | subowner | subenabled |                            subconninfo                            | subslotname | subsynccommit | subpublications 
---------+----------+----------+------------+-------------------------------------------------------------------+-------------+---------------+-----------------
12358 | fuga_sub |       10 | t          | host=pgsqlv11.example.com port=5432 user=postgres dbname=postgres | fuga_sub    | off           | {fuga_pub}
(1 row)
postgres=# 
postgres=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn  
---------+---------+------------+-----------
16402 |   16394 | r          | 0/1623FD0
(1 row)

SUBSCRIPTION 作成後に、Subscriber 側 (PostgreSQL 10 側) のテーブルを参照すると、Publisher 側 (PostgreSQL 11 側) のテーブルと同じ内容が INSERT されている (レプリケーションされている) ことが確認できます。

postgres=# SELECT * FROM fuga;
a  |                b                 
----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
(10 rows)

環境構築は以上ですが、特にエラー等もなく異なるメジャーバージョン間で Publisher/Subscriber を構築することができました。また、レプリケーションの情報は、以下の様に Publisher 側 (PostgreSQL 11 側) の pg_stat_replication から確認することができます。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 11.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# \x
Expanded display is on.
postgres=# 
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 1732
usesysid         | 10
usename          | postgres
application_name | fuga_sub
client_addr      | 172.20.0.3
client_hostname  | 
client_port      | 47068
backend_start    | 2018-11-07 08:09:45.024003+00
backend_xmin     | 
state            | streaming
sent_lsn         | 0/1624800
write_lsn        | 0/1624800
flush_lsn        | 0/1624800
replay_lsn       | 0/1624800
write_lag        | 
flush_lag        | 
replay_lag       | 
sync_priority    | 0
sync_state       | async

■検証 (動作確認)

それでは、構築した環境で動作検証 (INSERT/UPDATE/DELETE) を実施してみます。

まずは、INSERT です。Publisher 側 (PostgreSQL 11 側) で “a = 100, b = Replication Test” のレコードを INSERT します。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 11.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# INSERT INTO fuga VALUES (100, 'Replication Test');
INSERT 0 1
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
-----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
100 | Replication Test
(11 rows)

Publisher 側 (PostgreSQL 11 側) での INSERT 後、Subscriber 側 (PostgreSQL10 側) のテーブル “fuga” を参照すると、INSERT したレコードが反映されていることが確認できます。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 10.5 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
-----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
100 | Replication Test
(11 rows)

次に UPDATE です。Publisher 側 (PostgreSQL 11 側) で “a = 100” のレコードの b の値を “UPDATE Test” に UPDATE します。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 11.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# UPDATE fuga SET b = 'UPDATE Test' WHERE a = 100;
UPDATE 1
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
-----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
100 | UPDATE Test
(11 rows)

Publisher 側 (PostgreSQL 11 側) での UPDATE 後、Subscriber 側 (PostgreSQL10 側) のテーブル “fuga” を参照すると、UPDATE した値が反映されていることが確認できます。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 10.5 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
-----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
100 | UPDATE Test
(11 rows)

最後に DELETE です。Publisher 側 (PostgreSQL 11 側) で “a = 100” のレコードを DELETE します。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 11.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# DELETE FROM fuga WHERE a = 100;
DELETE 1
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
(10 rows)

Publisher 側 (PostgreSQL 11 側) での DELETE 後、Subscriber 側 (PostgreSQL10 側) のテーブル “fuga” を参照すると、DELETE したレコードが Subscriber 側でも削除されていることが確認できます。

postgres=# SELECT version();
version                                                 
---------------------------------------------------------------------------------------------------------
PostgreSQL 10.5 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)
postgres=# 
postgres=# SELECT * FROM fuga;
a  |                b                 
----+----------------------------------
1 | 4750ff430b2181824c22f5f0baebde08
2 | 4a89e898c8e0b59d0afca9c2e680c1d4
3 | d40e12cd68341558de86dbbbe6da0cd0
4 | 14411a5e768d8e17f675a07a34543e3f
5 | b68dac651ec1a87ee64ff24d242fd9e7
6 | d2424cbb2e4cd78e0642ab1f12c4f595
7 | ae6dbd4845e8918cb95e1e3c67146313
8 | aa70f94d09b9409a73c5228829c67494
9 | 8b5a69fbc37502569cfc0352482cbd98
10 | 2420de88524b4146becb1426a726f13d
(10 rows)

上記の様に、異なるメジャーバージョン間でのレプリケーションが実施できていることが確認できました。

■最後に

前回と今回の検証で、”10 -> 11″ / “11 -> 10” のどちらの方向であっても、異なるメジャーバージョン間でロジカルレプリケーションが実施できることを確認できました。

ロジカルレプリケーションは、PostgreSQL 10 で実装されたばかりでまだ制約等も多いのですが、今回の検証の様なメジャーバージョン間でのレプリケーションや、テーブル単位でのレプリケーションが可能であるため、様々なケースで利用することができるのではないかと思います。

ご覧いただきありがとうございます! この投稿は役に立ちましたか? 役に立った 役に立たなかった

Be the first to comment

コメント投稿

Your email address will not be published.


*