こんにちは。サイオステクノロジー OSS サポート担当 Y です。
今回は先日リリースされた PostgreSQL 11 を使って、異なるメジャーバージョン (PostgreSQL 10) との間でのロジカルレプリケーションを検証してみました。(※以下の内容は CentOS 7.5/PostgreSQL 10.5/PostgreSQL 11.0 にて検証しています。)
■はじめに
昨年リリースされた PostgreSQL 10 の新機能であるロジカルレプリケーションには “異なるメジャーバージョン間でレプリケーションが可能である” というメリットがあります。(PostgreSQL 9.x 以降で利用可能なストリーミングレプリケーションは、同一バージョン間でしかレプリケーションができません。)
しかし、このロジカルレプリケーションは PostgreSQL 10 で実装された機能であるため、実際に正式なメジャーバージョン間で検証をするためには PostgreSQL 11 がリリースされるまで待つ必要がありました。(PostgreSQL 11 の beta 版を使った検証はできていました。)
上記のような状況でしたが、先日 PostgreSQL 11 が正式にリリースされたため、今回は実際に異なるメジャーバージョン間でのロジカルレプリケーションを試してみました。
■検証 (環境構築)
それではさっそく、検証してみます。
今回は以下の様な構成で、PostgreSQL 10 から PostgreSQL 11 にデータをレプリケーションします。
[構成] -------------------------------------------------- PostgreSQL 10 : Publisher (いわゆる Master) PostgreSQL 11 : Subscriber (いわゆる Slave) --------------------------------------------------
まず初めに、Publisher である PostgreSQL 10 にて “wal_level = logical” の設定を実施し、PostgreSQL 10 を起動します (他の設定は、基本的デフォルト設定で動作するはずです)。また、既に PostgreSQL 10 が起動している場合は、wal_level の設定変更を反映させるために再起動が必要です。
[postgres@pgsqlv10 data]$ vim ./postgresql.conf
[postgres@pgsqlv10 data]$
[postgres@pgsqlv10 data]$ grep wal_level ./postgresql.conf
#wal_level = replica # minimal, replica, or logical
wal_level = logical # minimal, replica, or logical
[postgres@pgsqlv10 data]$
[postgres@pgsqlv10 data]$ pg_ctl start
waiting for server to start....2018-11-06 06:51:19.209 UTC [94] LOG: 00000: listening on IPv4 address "0.0.0.0", port 5432
2018-11-06 06:51:19.209 UTC [94] LOCATION: StreamServerPort, pqcomm.c:593
2018-11-06 06:51:19.210 UTC [94] LOG: 00000: listening on Unix socket "/tmp/.s.PGSQL.5432"
2018-11-06 06:51:19.210 UTC [94] LOCATION: StreamServerPort, pqcomm.c:587
2018-11-06 06:51:19.225 UTC [94] LOG: 00000: redirecting log output to logging collector process
2018-11-06 06:51:19.225 UTC [94] HINT: Future log output will appear in directory "log".
2018-11-06 06:51:19.225 UTC [94] LOCATION: SysLogger_Start, syslogger.c:634
done
server started
[postgres@pgsqlv10 data]$
[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)
PostgreSQL 10 を起動したら、テスト用のテーブル “hoge” を作成し、適当なデータを INSERT します。
postgres=# CREATE TABLE hoge (a int primary key, b text); CREATE TABLE postgres=# postgres=# INSERT INTO hoge SELECT a, md5(clock_timestamp()::text) FROM generate_series(1,10) AS a; INSERT 0 10 postgres=# postgres=# SELECT * FROM hoge; a | b ----+---------------------------------- 1 | 6d91123f36e3644c36c43684688aba59 2 | 3b6e280df8dce706a8c5ab211098cefa 3 | 0ca8e2468bcaad19f5c312f8e33d72cc 4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c 5 | fc8259410d5cf8a8f999317e8b54cf51 6 | 5455ab6e986844659aea4cd1f73533ef 7 | ca45ea91a839488007dd04faeb51726c 8 | 97e1bfe984b6171f96aed9955bb17e18 9 | 4f04f503606901fdac6d82671f88b76c 10 | 71402c5f4c3af4d2aa59b3680b83592b (10 rows)
次に Publisher として動作させるために PUBLICATION を作成します。作成した PUBLICATION に関する情報は、システムカタログの pg_publication や pg_publication_tables で確認することができます。これで PostgreSQL 10 側での設定は完了です。
postgres=# CREATE PUBLICATION hoge_pub FOR TABLE hoge; CREATE PUBLICATION postgres=# postgres=# SELECT * FROM pg_publication; pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete ----------+----------+--------------+-----------+-----------+----------- hoge_pub | 10 | f | t | t | t (1 row) postgres=# postgres=# SELECT * FROM pg_publication_tables; pubname | schemaname | tablename ----------+------------+----------- hoge_pub | public | hoge (1 row)
次に Subscriber である PostgreSQL 11 側の構築を行います。こちらは、特にデフォルト値からの設定変更は行わずに起動します。
[postgres@pgsqlv11 data]$ pg_ctl start
waiting for server to start....2018-11-06 06:54:29.449 UTC [109] LOG: 00000: listening on IPv4 address "0.0.0.0", port 5432
2018-11-06 06:54:29.449 UTC [109] LOCATION: StreamServerPort, pqcomm.c:593
2018-11-06 06:54:29.451 UTC [109] LOG: 00000: listening on Unix socket "/tmp/.s.PGSQL.5432"
2018-11-06 06:54:29.451 UTC [109] LOCATION: StreamServerPort, pqcomm.c:587
2018-11-06 06:54:29.466 UTC [109] LOG: 00000: redirecting log output to logging collector process
2018-11-06 06:54:29.466 UTC [109] HINT: Future log output will appear in directory "log".
2018-11-06 06:54:29.466 UTC [109] 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)
次に、レプリケーション対象のテーブル (Publisher である PostgreSQL 10 側で作成したテーブルと同じ定義のテーブル) を作成します。
postgres=# CREATE TABLE hoge (a int primary key, b text); CREATE TABLE postgres=# postgres=# SELECT * FROM hoge; a | b ---+--- (0 rows)
テーブルを作成したら、Subscriber として動作させるために SUBSCRIPTION を作成します。作成した SUBSCRIPTION に関する情報は、システムカタログの pg_subscription や pg_subscription_rel で確認することができます。
postgres=# CREATE SUBSCRIPTION hoge_sub CONNECTION 'host=pgsqlv10.example.com port=5432 user=postgres dbname=postgres' PUBLICATION hoge_pub;
NOTICE: created replication slot "hoge_sub" on publisher
CREATE SUBSCRIPTION
postgres=#
postgres=# SELECT * FROM pg_subscription;
subdbid | subname | subowner | subenabled | subconninfo | subslotname | subsynccommit | subpublications
---------+----------+----------+------------+-------------------------------------------------------------------+-------------+---------------+-----------------
12432 | hoge_sub | 10 | t | host=pgsqlv10.example.com port=5432 user=postgres dbname=postgres | hoge_sub | off | {hoge_pub}
(1 row)
postgres=#
postgres=# SELECT * FROM pg_subscription_rel;
srsubid | srrelid | srsubstate | srsublsn
---------+---------+------------+-----------
16393 | 16385 | r | 0/15EA8A8
(1 row)
SUBSCRIPTION 作成後に、Subscriber 側 (PostgreSQL 11 側) のテーブルを参照すると、Publisher 側 (PostgreSQL 10 側) のテーブルと同じ内容が INSERT されている (レプリケーションされている) ことが確認できます。
postgres=# SELECT * FROM hoge; a | b ----+---------------------------------- 1 | 6d91123f36e3644c36c43684688aba59 2 | 3b6e280df8dce706a8c5ab211098cefa 3 | 0ca8e2468bcaad19f5c312f8e33d72cc 4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c 5 | fc8259410d5cf8a8f999317e8b54cf51 6 | 5455ab6e986844659aea4cd1f73533ef 7 | ca45ea91a839488007dd04faeb51726c 8 | 97e1bfe984b6171f96aed9955bb17e18 9 | 4f04f503606901fdac6d82671f88b76c 10 | 71402c5f4c3af4d2aa59b3680b83592b (10 rows)
環境構築は以上ですが、特にエラー等もなく異なるメジャーバージョン間で Publisher/Subscriber を構築することができました。また、レプリケーションの情報は、以下の様に Publisher 側 (PostgreSQL 10 側) の pg_stat_replication から確認することができます。
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=# \x
Expanded display is on.
postgres=#
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 1716
usesysid | 10
usename | postgres
application_name | hoge_sub
client_addr | 172.20.0.2
client_hostname |
client_port | 45780
backend_start | 2018-11-07 08:07:59.657215+00
backend_xmin |
state | streaming
sent_lsn | 0/160EDD0
write_lsn | 0/160EDD0
flush_lsn | 0/160EDD0
replay_lsn | 0/160EDD0
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
■検証 (動作確認)
それでは、構築した環境で動作検証 (INSERT/UPDATE/DELETE) を実施してみます。
まずは、INSERT です。Publisher 側 (PostgreSQL 10 側) で “a = 100, b = Replication Test” のレコードを 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=# INSERT INTO hoge VALUES (100, 'Replication Test');
INSERT 0 1
postgres=#
postgres=# SELECT * FROM hoge;
a | b
-----+----------------------------------
1 | 6d91123f36e3644c36c43684688aba59
2 | 3b6e280df8dce706a8c5ab211098cefa
3 | 0ca8e2468bcaad19f5c312f8e33d72cc
4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c
5 | fc8259410d5cf8a8f999317e8b54cf51
6 | 5455ab6e986844659aea4cd1f73533ef
7 | ca45ea91a839488007dd04faeb51726c
8 | 97e1bfe984b6171f96aed9955bb17e18
9 | 4f04f503606901fdac6d82671f88b76c
10 | 71402c5f4c3af4d2aa59b3680b83592b
100 | Replication Test
(11 rows)
Publisher 側 (PostgreSQL 10 側) での INSERT 後、Subscriber 側 (PostgreSQL11 側) のテーブル “hoge” を参照すると、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=# SELECT * FROM hoge;
a | b
-----+----------------------------------
1 | 6d91123f36e3644c36c43684688aba59
2 | 3b6e280df8dce706a8c5ab211098cefa
3 | 0ca8e2468bcaad19f5c312f8e33d72cc
4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c
5 | fc8259410d5cf8a8f999317e8b54cf51
6 | 5455ab6e986844659aea4cd1f73533ef
7 | ca45ea91a839488007dd04faeb51726c
8 | 97e1bfe984b6171f96aed9955bb17e18
9 | 4f04f503606901fdac6d82671f88b76c
10 | 71402c5f4c3af4d2aa59b3680b83592b
100 | Replication Test
(11 rows)
次に UPDATE です。Publisher 側 (PostgreSQL 10 側) で “a = 100” のレコードの b の値を “UPDATE Test” に 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=# UPDATE hoge SET b = 'UPDATE Test' WHERE a = 100;
UPDATE 1
postgres=#
postgres=# SELECT * FROM hoge;
a | b
-----+----------------------------------
1 | 6d91123f36e3644c36c43684688aba59
2 | 3b6e280df8dce706a8c5ab211098cefa
3 | 0ca8e2468bcaad19f5c312f8e33d72cc
4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c
5 | fc8259410d5cf8a8f999317e8b54cf51
6 | 5455ab6e986844659aea4cd1f73533ef
7 | ca45ea91a839488007dd04faeb51726c
8 | 97e1bfe984b6171f96aed9955bb17e18
9 | 4f04f503606901fdac6d82671f88b76c
10 | 71402c5f4c3af4d2aa59b3680b83592b
100 | UPDATE Test
(11 rows)
Publisher 側 (PostgreSQL 10 側) での UPDATE 後、Subscriber 側 (PostgreSQL11 側) のテーブル “hoge” を参照すると、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=# SELECT * FROM hoge;
a | b
-----+----------------------------------
1 | 6d91123f36e3644c36c43684688aba59
2 | 3b6e280df8dce706a8c5ab211098cefa
3 | 0ca8e2468bcaad19f5c312f8e33d72cc
4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c
5 | fc8259410d5cf8a8f999317e8b54cf51
6 | 5455ab6e986844659aea4cd1f73533ef
7 | ca45ea91a839488007dd04faeb51726c
8 | 97e1bfe984b6171f96aed9955bb17e18
9 | 4f04f503606901fdac6d82671f88b76c
10 | 71402c5f4c3af4d2aa59b3680b83592b
100 | UPDATE Test
(11 rows)
最後に DELETE です。Publisher 側 (PostgreSQL 10 側) で “a = 100” のレコードを DELETE します。
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=# DELETE FROM hoge WHERE a = 100;
DELETE 1
postgres=#
postgres=# SELECT * FROM hoge;
a | b
----+----------------------------------
1 | 6d91123f36e3644c36c43684688aba59
2 | 3b6e280df8dce706a8c5ab211098cefa
3 | 0ca8e2468bcaad19f5c312f8e33d72cc
4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c
5 | fc8259410d5cf8a8f999317e8b54cf51
6 | 5455ab6e986844659aea4cd1f73533ef
7 | ca45ea91a839488007dd04faeb51726c
8 | 97e1bfe984b6171f96aed9955bb17e18
9 | 4f04f503606901fdac6d82671f88b76c
10 | 71402c5f4c3af4d2aa59b3680b83592b
(10 rows)
Publisher 側 (PostgreSQL 10 側) での DELETE 後、Subscriber 側 (PostgreSQL11 側) のテーブル “hoge” を参照すると、DELETE したレコードが Subscriber 側でも削除されていることが確認できます。
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=# SELECT * FROM hoge;
a | b
----+----------------------------------
1 | 6d91123f36e3644c36c43684688aba59
2 | 3b6e280df8dce706a8c5ab211098cefa
3 | 0ca8e2468bcaad19f5c312f8e33d72cc
4 | 8b8dd9bdd4f3e152ce7e72a3b422e77c
5 | fc8259410d5cf8a8f999317e8b54cf51
6 | 5455ab6e986844659aea4cd1f73533ef
7 | ca45ea91a839488007dd04faeb51726c
8 | 97e1bfe984b6171f96aed9955bb17e18
9 | 4f04f503606901fdac6d82671f88b76c
10 | 71402c5f4c3af4d2aa59b3680b83592b
(10 rows)
上記の様に、異なるメジャーバージョン間でのレプリケーションが実施できていることが確認できました。
■最後に
PostgreSQL 10 で実装されたロジカルレプリケーションを使って、異なるメジャーバージョン間でのレプリケーションを実施することができました。次回は、今回と逆方向のレプリケーション (PostgreSQL 11 から PostgreSQL 10 へのレプリケーション) を検証してみようと思います。


古い記事にコメント付けちゃってますが、10と11の間では大丈夫ですね
もっと上のバージョン(ubuntu 24.04 のPostgreSQL16.9とその上のバージョン(PostgreSQL17?)ではどうでしょうか?
一度試してみますね^^
コメントありがとうございます。こちらでも折を見てご提示バージョンでの確認やブログの公開等を検討してまいります。