はじめに
今日はPostgreSQL 10の目玉機能の一つになるであろう、ロジカルレプリケーションを使ってみた話を書きますよ。
参考にしたもの
実はPostgreSQL 10のロジカルレプリケーションに関しては、postgresql-jp Slackで、篠田さん@HPEや前JPUG理事長の永安さんが簡単に検証した例を紹介しているので、そっちを見ればいいのだろうけど、まあこういうのは自分で手を動かさないと覚えないので、自分でもやってみることにする。
ロジカルレプリケーションって何よ?
名前のとおり、論理WALを伝播させてレプリケーションさせる機能。
PostgreSQL 9.0から導入されたストリーミングレプリケーションは物理レプリケーションであり、WALをそのままダイレクトに反映させる機構。なので、レプリケーション元/先のメジャーバージョンやOSアーキテクチャが異なると適用できなかった。
PostgreSQL 10のロジカルレプリケーションは、異なるバージョンや異なるOSアーキテクチャ間でも適用が可能になる(はず)。また、ストリーミングレプリケーションでは、データベースクラスタ全体がレプリケーション対象となるため、特定のテーブルのみをレプリケーションしたいという用途には使えなかった。
PostgreSQL 9.4からサポートされているロジカルデコーディングの技術をベースにしている。今まではプラグインや論理WALを反映させる機構の作成が必要だった。
自分もロジカルデコーディングを使って、PostgreSQLのWALをグラフデータベースNeo4jに反映させてみる、というを作って遊んでいたりしてたけど、まあ、ぶっちゃけ面倒です。
ロジカルレプリケーションでは、幾つかのSQLコマンドを叩くだけで、ロジカルデコーディングでやっていた論理WALへの変換とレプリケーション先への反映をやってくれるというものになっている(はず)。
じゃあ、早速使ってみようか。なお、検証に使った版は今日の最新ソースをベースにしたものなんだけど、まだまだ開発途中の版なので、beta版リリース時には仕様等、ちょっと変わっているかもしれないので悪しからず。
準備
postgresql.conf
ロジカルレプリケーションもストリーミングレプリケーションに類似した設定が必要になってくる。
ロジカルレプリケーションを動作させるためには、最低限、以下のパラメータの変更がレプリケーション元のサーバには必要になる。
パラメータ名 | 設定 | 説明 |
---|---|---|
wal_level | logical | SRの場合にはreplicaでいいが、ロジカルレプリケーションの場合はlogical必須 |
max_wal_senders | 1より大きい値 | SRと併用する場合、その数の考慮要 |
max_replication_slots | 1より大きい値 | 論理レプリケーション要のスロット数。SRでスロットを併用する場合はそれも考慮要 |
pg_hba.conf
ロジカルレプリケーションもレプリケーションプロトコルを使った接続を行うので、ストリーミングレプリケーションと同様にpg_hba.confにreplicationデータベースとして登録しておく。
今回は面倒なのでpostgresのままで設定したが、実際に運用する場合には、レプリケーション専用ロールを使って接続させるのが良さげ。
ロジカルレプリケーションの設定
レプリケーションの設定は、ソースと反映先の2つに設定が必要になる。
ひじょーにざっくり書くと、以下のような設定を行う。
Slony-Iとかの経験がある人だと、「あー、そんな用語だったねー」と思うはず。
- レプリケーション元
- レプリケーション対象のテーブルを指定する。PKを持つテーブルにしておくのが無難。
- CREATE PUBLICATIONコマンドでレプリケーション元の設定を行う。このときにロジカルレプリケーション対象のテーブルを選択する。
- たぶんDB全体とか、そういうまるっとした設定もできるはず。
- レプリケーション先
- レプリケーション先のテーブルを指定する。これもPKを持たせておかないと、後々いろいろ面倒なことになりそう。つーか、とりあえずはレプリケーション元に合わせて作っておくが吉。
- CREATE SUBSCRIPTIONの購読先を指定する。このときには先だって作成していたロジカルレプリケーション元を指定する。
検証モデル
今回は同一Linuxマシン上にport=5432とport=5433の2つのデータベースクラスタを作成してそれを起動し、port=5432側(srv1)のtestdb内のjapan表をport=5433側(srv2)へ論理レプリケーションするモデルにした。
また、このモデルにより、町田問題が解決するのかを検証した。
検証その1
srv1側
まず、何も考えずテーブルを定義する(これが後で後悔する原因となる)。
CREATE TABLE japan (id int, pref text, city text, data text);
CREATE PUBLICATION pub_srv1_testdb_japan FOR TABLE japan;
2行目がレプリケーション元となるテーブルを指定するためのPUBLICATION構文である。
srv2側
レプリケーションの受け側でも、テーブルは同じように作成しておく。
レプリケーションの受け側ではPUBLICATION ではなく、SUBSCRIPTIONを作成する。
testdb=# CREATE TABLE japan (id int, pref text, city text, data text);
CREATE TABLE
testdb=# CREATE SUBSCRIPTION sub_srv2_testdb_japan CONNECTION 'dbname=testdb port=5432 user=postgres' PUBLICATION pub_srv1_testdb_japan;
NOTICE: created replication slot "sub_srv2_testdb_japan" on publisher
CREATE SUBSCRIPTION
SUBSCRIPTIONのPUBLICATION句には、既に存在しているPUBLICATIONを指定する必要がある(が、存在チェックとかは今のところしてなさそう?)。
また、SUBSCRIPTIONに指定する名前と同じ名前のものが、レプリケーション送り元に生成されるっぽい。
これでjapanテーブルの内容がレプリケーションされるはず。
挿入内容をレプリケーションする
srv1側のjapanテーブルにINSERT文で挿入してみる。
testdb=# INSERT INTO japan VALUES (1, '東京', '大田', 'らーめん 潤');
INSERT 0 1
testdb=# INSERT INTO japan VALUES (2, '神奈川', '横浜', '麺恋亭');
INSERT 0 1
testdb=# TABLE japan;
id | pref | city | data
----+--------+------+-------------
1 | 東京 | 大田 | らーめん 潤
2 | 神奈川 | 横浜 | 麺恋亭
(2 rows)
srv2側のjapanテーブルを参照してみよう。
testdb=# SELECT * FROM japan;
id | pref | city | data
----+--------+------+-------------
1 | 東京 | 大田 | らーめん 潤
2 | 神奈川 | 横浜 | 麺恋亭
(2 rows)
やったね♪ きちんとsrv2側にも反映されました。
さて、ここでpgdata2のjapanにデータを挿入してみます。
testdb=# INSERT INTO japan VALUES (3, '神奈川', '町田', '竹之助');
INSERT 0 1
testdb=# TABLE japan;
id | pref | city | data
----+--------+------+-------------
1 | 東京 | 大田 | らーめん 潤
2 | 神奈川 | 横浜 | 麺恋亭
3 | 神奈川 | 町田 | 竹之助
(3 rows)
prefが神奈川でcityが町田。何か間違ってるっけ?
ストリーミングレプリケーションとは異なり、反映先のテーブルにもフツーに挿入できます。これがロジカルレプリケーションの面白いところ。
さて、この状態でsrv1に、以下のようなINSERT文を使って挿入してみます。
testdb=# INSERT INTO japan VALUES (3, '神奈川', '町田', '竹之助');
INSERT 0 1
testdb=# TABLE japan;
id | pref | city | data
----+--------+------+-------------
1 | 東京 | 大田 | らーめん 潤
2 | 神奈川 | 横浜 | 麺恋亭
3 | 神奈川 | 町田 | 竹之助
(3 rows)
あれ、フツーに挿入されちゃったよ。
この状態でsrv2側のjapanテーブルを参照してみると
testdb=# TABLE japan;
id | pref | city | data
----+--------+------+-------------
1 | 東京 | 大田 | らーめん 潤
2 | 神奈川 | 横浜 | 麺恋亭
3 | 神奈川 | 町田 | 竹之助
3 | 神奈川 | 町田 | 竹之助
(4 rows)
あ・・・これなんかアカンやつだw
TRUNCATEしてみる
とりあえず、きれいな状態に戻したいので、srv1側でTRUNCATEしてみる。
testdb=# TRUNCATE japan;
TRUNCATE TABLE
testdb=# TABLE japan;
id | pref | city | data
----+------+------+------
(0 rows)
で、srv2側のjapanテーブルを参照してみると・・・
testdb=# TABLE japan;
id | pref | city | data
----+--------+------+-------------
1 | 東京 | 大田 | らーめん 潤
2 | 神奈川 | 横浜 | 麺恋亭
3 | 神奈川 | 町田 | 竹之助
3 | 神奈川 | 町田 | 竹之助
(4 rows)
(ノ∀`)アチャー
どうやら、現状はTRUNCATEはロジカルレプリケーションの対象になっていないようだ。
なので、TRUNCATEをかける場合には、レプリケーション元であるsrv1にもレプリケーション先であるsrv2の両方にTRUNCATEをかける必要があるようだ。めんどくせえ。
ぬーん、TRUNCATEのWALって出力されているはずなのに。
まあ、まだ開発中のバージョンだし、このへんは今後改善されていくと思います。
仕方ないのでpgdata2側も手動でTRUNCATEする。
testdb=# TRUNCATE japan;
TRUNCATE TABLE
testdb=# TABLE japan;
id | pref | city | data
----+------+------+------
(0 rows)
COPYでバルクロードしてみる
srv1のjapanテーブルに対して、以下のようなデータをCOPYでバルクロードする。
$ cat /tmp/japan.txt
1 東京 品川 丸直
2 東京 八丈島 蓮華
3 静岡 熱海 雨風本舗
4 静岡 藤枝 池田屋
5 神奈川 横浜 麺恋亭
6 神奈川 横浜 吉村家
7 神奈川 川崎 クマさん
8 神奈川 川崎 ニュータンタン本舗 本店
9 神奈川 町田 竹の助
testdb=# COPY japan FROM '/tmp/japan.txt';
COPY 9
testdb=# TABLE japan;
id | pref | city | data
----+--------+--------+-------------------------
1 | 東京 | 品川 | 丸直
2 | 東京 | 八丈島 | 蓮華
3 | 静岡 | 熱海 | 雨風本舗
4 | 静岡 | 藤枝 | 池田屋
5 | 神奈川 | 横浜 | 麺恋亭
6 | 神奈川 | 横浜 | 吉村家
7 | 神奈川 | 川崎 | クマさん
8 | 神奈川 | 川崎 | ニュータンタン本舗 本店
9 | 神奈川 | 町田 | 竹の助
(9 rows)
COPYもフツーに出来ますね。
この状態でsrv2側も参照してみる。
testdb=# TABLE japan;
id | pref | city | data
----+--------+--------+-------------------------
1 | 東京 | 品川 | 丸直
2 | 東京 | 八丈島 | 蓮華
3 | 静岡 | 熱海 | 雨風本舗
4 | 静岡 | 藤枝 | 池田屋
5 | 神奈川 | 横浜 | 麺恋亭
6 | 神奈川 | 横浜 | 吉村家
7 | 神奈川 | 川崎 | クマさん
8 | 神奈川 | 川崎 | ニュータンタン本舗 本店
9 | 神奈川 | 町田 | 竹の助
(9 rows)
うん。COPYも問題なく使えそう。
UPDATE
じゃあ、次はUPDATEしてみよう。
町田は東京だという妄言を吐く人が町田のprefを東京に変えようとしてUPDATE文を発行してみるが、
testdb=# UPDATE japan SET pref = '東京' WHERE id = 9;
ERROR: cannot update table "japan" because it does not have replica identity and publishes updates
HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
testdb=#
アバーッ!このように、更新に失敗してしまう。
これは 町田が神奈川だから更新に失敗する のではなく、replica identityというものを設定しないとUPDATEとDELETEはできないっぽい。
とりあえずid にUNIQUE INDEX張って、ALTER TABLEでREPLICA IDENTITYを設定してみるか・・・。
testdb=# CREATE UNIQUE INDEX japan_id ON japan (id);
CREATE INDEX
testdb=#
testdb=# ALTER TABLE japan REPLICA IDENTITY USING INDEX japan_id ;
ERROR: index "japan_id" cannot be used as replica identity because column "id" is nullable
testdb=#
グワーッ!UNIQUE+NULLABLEでないといけない,つまりPrimary Keyが存在し、それをREPLICA IDENTITYに設定しないといけないのな。
一旦、テーブルと、PUBLISHER、SUBSCRIBEを作り直すか・・・
PUBLISHERとSUBSCRIBEの削除
とりあえずsrv1側のjapanテーブルを削除してみる。
testdb=# DROP TABLE japan CASCADE ;
DROP TABLE
testdb=#
これでPUBLICATIONも消えるのかな・・・と思ったら消えてない。
testdb=# TABLE pg_publication;
pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete
-----------------------+----------+--------------+-----------+-----------+-----------
pub_srv1_testdb_japan | 10 | f | t | t | t
(1 row)
どうやら、PUBLISHERはテーブルとは依存関係にはないようだ。
あれかなー、PCREATE PUBLICATIONは、対象が表だけじゃなくてDB全体とか指定ができたりするからかな。
仕方ないからDROP PUBLICATIONで削除する。
testdb=# DROP PUBLICATION pub_srv1_testdb_japan;
DROP PUBLICATION
testdb=# TABLE pg_publication;
pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete
---------+----------+--------------+-----------+-----------+-----------
(0 rows)
pgdata2側のTABLEとSUBSCRIBERも同様に削除する。
testdb=# DROP SUBSCRIPTION sub_srv2_testdb_japan;
NOTICE: dropped replication slot "sub_srv2_testdb_japan" on publisher
DROP SUBSCRIPTION
testdb=# DROP TABLE japan ;
DROP TABLE
testdb=# TABLE pg_subscription;
subdbid | subname | subowner | subenabled | subconninfo | subslotname | subpublications
---------+---------+----------+------------+-------------+-------------+-----------------
(0 rows)
SUBSCRIPTIONを削除すると、publisher(pgdata1側)の同名slotも削除されるようだ。
とりあえずこれで仕切り直しだ。
検証2 - primary key制約付きの表で再作成
japanテーブルのidをprimary keyとするようにして再定義してみる。
testdb=# CREATE TABLE japan (id int, pref text, city text, data text);
CREATE TABLE
testdb=# CREATE UNIQUE INDEX japan_id ON japan (id);
CREATE INDEX
testdb=# ALTER TABLE japan ADD PRIMARY KEY USING INDEX japan_id ;
ALTER TABLE
testdb=#
え、なんでid intの定義にprimary key を指定しないかだって?
それはPostgreSQL 10のパーティションテーブルにprimary keyが設定できないからだよっ!(後々、パーティションの一部のテーブルだけロジカルレプリケーションするという検証をしたいので)
それはさておき、PUBLICATIONを再度設定してみる。
CREATE PUBLICATION pub_srv1_testdb_japan FOR TABLE japan;
pgdata2側も同じようにテーブル定義、インデックス定義、プライマリキー定義をしておく。
testdb=# CREATE TABLE japan (id int, pref text, city text, data text);
CREATE TABLE
testdb=# CREATE UNIQUE INDEX japan_id ON japan (id);
CREATE INDEX
testdb=# ALTER TABLE japan ADD PRIMARY KEY USING INDEX japan_id ;
ALTER TABLE
testdb=#
で、SUBSCRIPTIONを再度定義する。
CREATE SUBSCRIPTION sub_srv2_testdb_japan CONNECTION 'dbname=testdb port=5432 user=postgres' PUBLICATION pub_srv1_testdb_japan;
testdb=# CREATE SUBSCRIPTION sub_srv2_testdb_japan CONNECTION 'dbname=testdb port=5432 user=postgres' PUBLICATION pub_srv1_testdb_japan;
NOTICE: created replication slot "sub_srv2_testdb_japan" on publisher
CREATE SUBSCRIPTION
testdb=#
UPDATE再検証
さっきと同じようにsrv1のjapanテーブルに対してCOPYでデータをロードしておく。
ロード後にsrv1はこうなっている。
testdb=# TABLE japan;
id | pref | city | data
----+--------+--------+-------------------------
1 | 東京 | 品川 | 丸直
2 | 東京 | 八丈島 | 蓮華
3 | 静岡 | 熱海 | 雨風本舗
4 | 静岡 | 藤枝 | 池田屋
5 | 神奈川 | 横浜 | 麺恋亭
6 | 神奈川 | 横浜 | 吉村家
7 | 神奈川 | 川崎 | クマさん
8 | 神奈川 | 川崎 | ニュータンタン本舗 本店
9 | 神奈川 | 町田 | 竹の助
(9 rows)
少し経つと、srv2側のjapanテーブルにも更新内容が伝播されているのがわかる。
testdb=# TABLE japan;
id | pref | city | data
----+--------+--------+-------------------------
1 | 東京 | 品川 | 丸直
2 | 東京 | 八丈島 | 蓮華
3 | 静岡 | 熱海 | 雨風本舗
4 | 静岡 | 藤枝 | 池田屋
5 | 神奈川 | 横浜 | 麺恋亭
6 | 神奈川 | 横浜 | 吉村家
7 | 神奈川 | 川崎 | クマさん
8 | 神奈川 | 川崎 | ニュータンタン本舗 本店
9 | 神奈川 | 町田 | 竹の助
(9 rows)
とりあえずUPDATEできるか再確認する。
pgdata2側も更新が伝播されてますねー。
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+------+------+--------
9 | 東京 | 町田 | 竹の助
(1 row)
町田は東京に奪われました・・・ぐぬぬ。
重複エラーとなるINSERT
pgdata1からキー重複のあるINSERTももちろん、エラーになる。
testdb=# INSERT INTO japan VALUES (9, '神奈川', '町田', '竹之助');
ERROR: duplicate key value violates unique constraint "japan_id"
DETAIL: Key (id)=(9) already exists.
testdb=#
pgdata2から挿入しても同様。
testdb=# INSERT INTO japan VALUES (9, '神奈川', '町田', '竹之助');
ERROR: duplicate key value violates unique constraint "japan_id"
DETAIL: Key (id)=(9) already exists.
testdb=#
DELETE
こんなに苦しいのなら悲しいのなら……町田などいらぬ!というわけではないのだが、DELETEもやってみる。
が、今回はちょいと一捻り。
まずBEGINしてDELETEする。
そうするとpgdata1上はもちろんこうなる。
testdb=# BEGIN;
BEGIN
testdb=# DELETE FROM japan WHERE id = 9;
DELETE 1
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+------+------+------
(0 rows)
では、このときにpgdata2上はどう見えてみるのか。
はい、もちろんCOMMITされていない=WALを生成していないのでpgdata2上は削除されていない。
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+------+------+--------
9 | 東京 | 町田 | 竹の助
(1 row)
testdb=#
で、このときに、pgdata2上で町田の店を削除してCOMMITし、その後にpgdata1側をCOMMITするとどうなるのか。
testdb=# COMMIT;
COMMIT
testdb=#
pgdata1側でCOMMITしてみる。
testdb=# COMMIT;
COMMIT
testdb=#
あらら、この場合はしれっと両方とも削除とCOMMITに成功しちゃいますね。
なんかイヤーンな感じ。
挿入のコンフリクト
さて、現在はpgdata1→pgdata2の片方向のレプリケーションしか設定していない。しかし、pgdata2側のjapanは更新可能である。
では、両方の更新がコンフリクトしたらどうなるのか。
これはなかなか面倒そうな話ですねー。
コンフリクト検証は別途、みっちりやらねばと思うけど、とりあえず、簡単なケースを今回は1つだけやってみる。
INSERT時のキーが重複するようなケースだ。
まず、srv2側(反映先)のトランザクションを先にINSERTまで実施する。
testdb=# BEGIN;
BEGIN
testdb=# INSERT INTO japan VALUES (9, '東京都', '町田', 'RA-MEN 3SO');
INSERT 0 1
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+--------+------+------------
9 | 東京都 | 町田 | RA-MEN 3SO
(1 row)
その後に、pgdata1側のトランザクションでINSERTまで実施する。
testdb=# BEGIN;
BEGIN
testdb=# INSERT INTO japan VALUES (9, '神奈川', '町田', 'RA-MEN 3SO');
INSERT 0 1
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+--------+------+------------
9 | 神奈川 | 町田 | RA-MEN 3SO
(1 row)
この状態で、pgdata2側がコミットする。
testdb=# COMMIT;
COMMIT
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+--------+------+------------
9 | 東京都 | 町田 | RA-MEN 3SO
(1 row)
pgdata1側がその後にコミットする
testdb=# COMMIT;
COMMIT
testdb=#
ふむ。
srv2側を見ると、
testdb=# SELECT * FROM srv WHERE id = 9;
id | pref | city | data
----+--------+------+------------
9 | 東京都 | 町田 | RA-MEN 3SO
(1 row)
げげ、レプリケーションが破綻しとるがなw
testdb=# INSERT INTO japan VALUES (10, '山梨', '大月', '喜楽');
INSERT 0 1
testdb=# SELECT * FROM japan WHERE id = 10;
id | pref | city | data
----+------+------+------
10 | 山梨 | 大月 | 喜楽
(1 row)
この後にpgdata2側
testdb=# SELECT * FROM japan WHERE id = 10;
id | pref | city | data
----+------+------+------
(0 rows)
を参照してみるが、レプリケーションされてない。
srv1側には実はこんなエラーがしれっと出ている。
2017-02-19 19:10:39.583 JST [7842] LOG: starting logical decoding for slot "sub_srv2_testdb_japan"
2017-02-19 19:10:39.583 JST [7842] DETAIL: streaming transactions committing after 0/16A0920, reading WAL from 0/16A0340
2017-02-19 19:10:39.583 JST [7842] LOG: logical decoding found consistent point at 0/16A0340
2017-02-19 19:10:39.583 JST [7842] DETAIL: There are no running transactions.
2017-02-19 19:10:39.585 JST [7842] LOG: could not receive data from client: Connection reset by peer
2017-02-19 19:10:39.585 JST [7842] LOG: unexpected EOF on standby connection
また、srv2側には実はこんなエラーがしれっと出ている。
2017-02-19 19:10:39.584 JST [7841] ERROR: duplicate key value violates unique constraint "japan_id"
2017-02-19 19:10:39.584 JST [7841] DETAIL: Key (id)=(9) already exists.
2017-02-19 19:10:39.585 JST [7108] LOG: worker process: logical replication worker for subscription 16406 (PID 7841) exited with exit code 1
2017-02-19 19:10:44.586 JST [7115] LOG: starting logical replication worker for subscription "sub_srv2_testdb_japan"
2017-02-19 19:10:44.588 JST [7847] LOG: logical replication apply for subscription "sub_srv2_testdb_japan" has started
2017-02-19 19:10:44.592 JST [7847] ERROR: duplicate key value violates unique constraint "japan_id"
2017-02-19 19:10:44.592 JST [7847] DETAIL: Key (id)=(9) already exists.
さて、この状態からどうやって復旧するんだろう・・・
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+--------+------+------------
9 | 東京都 | 町田 | RA-MEN 3SO
(1 row)
さて、このエラーだが、これは 東京が不当に町田を所有しているからエラー ・・・になるのではなく、id=9の行がpgdata2側に存在するために、pgdata1側のid=9のINSERTが成功せず、その後のINSERTも反映を待っている、ということなんだろう。
なので、pgdata2のid=9の行を削除する。
DELETE直後にみると
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+------+------+------
(0 rows)
あれ?行がない。
が、ほんのすこし経過すると、
testdb=# SELECT * FROM japan WHERE id = 9;
id | pref | city | data
----+--------+------+------------
9 | 神奈川 | 町田 | RA-MEN 3SO
(1 row)
testdb=# SELECT * FROM japan WHERE id = 10;
id | pref | city | data
----+------+------+------
10 | 山梨 | 大月 | 喜楽
(1 row)
pgdata1側のid=9のINSERTが反映され、その後のid=10のINSERTも反映される。
おもしろーい!
これから検証すること。
- マルチマスタ構成
- 様々なコンフリクト
- パーティションとの組み合わせ
これはいろいろ試しがいのある機能だぜ・・・。
まとめ
- ロジカルレプリケーションではテーブル単位にレプリケーション対象が指定可能。
- 反映元ではCREATE PUBLICAGTIONコマンドを実行させること。
- 反映先では、CREATE SUBSCRIPTIONコマンドを実行させること。
- 現状はTRUNCATEはロジカルレプリケーションはきちんと動作しないよ。要検証。
- 反映元のテーブルにはPK相当を持たせること。でないとUPDATEやDELETEができなくなる。
- 反映先へ更新がある場合、レプリケーション接続が切れるケースがある。要注意。
- 挙動が変な場合、サーバログを確認すべし。
- 町田は神奈川。