ロジカルレプリケーションで色々試してみる

サブスクライバにテーブル作成していなかったらどうなる?

環境構築

前回のファイルを利用してコンテナを作成したら、確認のために次のコマンドを実行して、
指定するpostgresql.confファイルが読み込まれていることを確認する。

show config_file;

config_fileの場所として、
/etc/postgresql/postgresql.conf が指定されていれば良い。

プライマリでの作業

create table table1 (id integer, data varchar(10));

insert into table1 values(1, 'data1');
insert into table1 values(2, 'data2');
insert into table1 values(3, 'data3');

CREATE PUBLICATION test_publication FOR TABLE table1;

サブスクライバでの作業

CREATE SUBSCRIPTION test_subscription
    CONNECTION 'host=PrimaryPostgreSQL port=5432 dbname=TestDB user=shinke1987 password=password'
    PUBLICATION test_publication;

上記コマンドを実行すると、次のエラーが発生する。

[42P01] ERROR: relation "public.table1" does not exist

テーブルは自動で作成されない。

スキーマが一致していなかったらどうなる?

サブスクライバでの作業

上のエラーが出た状態から続きを行う。

-- スキーマ作成。
CREATE SCHEMA TestSchema;

-- テーブル作成。
CREATE TABLE TestSchema.table1
(
    id   integer,
    data varchar(10)
);

-- サブスクライバ作成。
CREATE SUBSCRIPTION test_subscription
    CONNECTION 'host=PrimaryPostgreSQL port=5432 dbname=TestDB user=shinke1987 password=password'
    PUBLICATION test_publication;

上記コマンドを実行すると、次のエラーが発生する。

[42P01] ERROR: relation "public.table1" does not exist

テーブルは自動で作成されない。

DROP SUBSCRIPTIONを実行するとサブスクライバのテーブルは削除される?

サブスクライバでの作業

上のエラーが出た状態から続きを行う。

-- publicスキーマにテーブル作成。
CREATE TABLE table1
(
    id   integer,
    data varchar(10)
);

-- サブスクライバ作成。
CREATE SUBSCRIPTION test_subscription
    CONNECTION 'host=PrimaryPostgreSQL port=5432 dbname=TestDB user=shinke1987 password=password'
    PUBLICATION test_publication;

-- 同期されていることを確認。
SELECT * FROM table1;

-- サブスクリプションを削除。
DROP SUBSCRIPTION test_subscription;

上記コマンドを実行すると、次のメッセージが表示される。

dropped replication slot "test_subscription" on publisher

次にテーブルやその内容が削除されているか確認するために次のSQLを実行する。

SELECT * FROM table1;

削除されていなかった。

次にサブスクリプションが削除されているかを確認するために次のSQLを実行する。

SELECT * FROM pg_subscription WHERE subname = 'test_subscription';

削除されていた。

再度同じコマンドを利用してサブスクリプションを作成し、プライマリでデータを1件挿入すると次の結果になった。

元々存在していた(1回目のロジカルレプリケーションの同期内容)は削除されずに、
今のプライマリのテーブル内容が追加された形になった。

同期してコンフリクトが起こるとどうなる?

環境構築

前回のファイルを利用してコンテナを作成したら、確認のために次のコマンドを実行して、
指定するpostgresql.confファイルが読み込まれていることを確認する。

show config_file;

config_fileの場所として、
/etc/postgresql/postgresql.conf が指定されていれば良い。

プライマリでの作業

-- テーブル作成。
CREATE TABLE public.table1 (
    id integer,
    data varchar(10)
);

-- データ挿入。
insert into table1 values(1, 'data1');
insert into table1 values(2, 'data2');
insert into table1 values(3, 'data3');

-- パブリケーション作成。
CREATE PUBLICATION test_publication FOR TABLE table1;

サブスクライバでの作業

-- テーブル作成。
CREATE TABLE public.table1 (
    id integer unique,
    data varchar(10)
);

-- データ挿入。
INSERT INTO table1 VALUES(1, 'data1-1');

-- サブスクリプション作成。
CREATE SUBSCRIPTION test_subscription
    CONNECTION 'host=PrimaryPostgreSQL port=5432 dbname=TestDB user=shinke1987 password=password'
    PUBLICATION test_publication;

上記コマンドを実行すると、次のメッセージが表示された。

created replication slot "test_subscription" on publisher

次のSQLを実行し、テーブルのデータがどうなっているか確認する。

SELECT * FROM table1;

先ほどサブスクライバで挿入したデータ1件しか入っていなかった。
(同期されなかった)

サブスクライバのログを見るとこのように表示されていた。

[79] LOG:  logical replication apply worker for subscription "test_subscription" has started
[80] LOG:  logical replication table synchronization worker for subscription "test_subscription", table "table1" has started
[80] ERROR:  duplicate key value violates unique constraint "table1_id_key"
[80] DETAIL:  Key (id)=(1) already exists.
[80] CONTEXT:  COPY table1, line 1
[1] LOG:  background worker "logical replication worker" (PID 80) exited with exit code 1

定期的に再実行・再同期しているようなので、サブスクライバのテーブルからコンフリクトしているデータを削除する。

TRUNCATE table1;

3秒ほどしてテーブルの内容をSELECT文で表示すると、プライマリのデータが同期されていた。

同期中にプライマリがダウンしたらどうなる?

上のプライマリのデータが同期されている状態で、プライマリのコンテナだけを停止すると、
約1秒後に次のログが流れた。

[249] ERROR:  could not connect to the publisher: could not translate host name "PrimaryPostgreSQL" to address: Name or service not known
[1] LOG:  background worker "logical replication worker" (PID 249) exited with exit code 1
[250] LOG:  logical replication apply worker for subscription "test_subscription" has started
[250] ERROR:  could not connect to the publisher: could not translate host name "PrimaryPostgreSQL" to address: Name or service not known
[1] LOG:  background worker "logical replication worker" (PID 250) exited with exit code 1

この状態でプライマリのコンテナを起動すると、
上のプライマリに接続できないといったログは表示されないようになった。

次にプライマリでテーブルにデータを挿入すると、
サブスクライバのテーブルにデータは同期された。

コメント

タイトルとURLをコピーしました