tail -f /dev/null

If you haven't had any obstacles lately, you're not challenging. be the worst.

PostgreSQLの論理レプリケーション構成において、サブスクライバが落ち続けた場合の影響

Environment

  • PostgreSQL v13
  • wal disk 10GB
  • max_wal_size 30MB

Preparation

パブリッシャ

walは8.3G余りの状態

# df -h
ファイルシス                                          サイズ  使用  残り 使用% マウント位置
/dev/mapper/xlog      10G  1.8G  8.3G   18% /test/pg_wal

テスト用のテーブルを作成する。

CREATE TABLE test.test_publication_table (
    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    data TEXT
);

パブリケーションを作成する。

CREATE PUBLICATION test_publication FOR TABLE test.test_publication_table;

サブスクライバ

サブスクリプションを作成する。

CREATE SUBSCRIPTION test_subscription
CONNECTION 'host=xxx dbname=xxx user=xxx password=xxx port=xxx application_name=test_subscription' PUBLICATION test_publication;

レプリケーションがasyncであることを確認する。

select * from pg_stat_replication;
 pid  | usesysid |  usename  |     application_name      | client_addr | client_hostname | client_port |         backend_start         | backend_xmin |   state   |  sent_lsn  | write_lsn  | flush_lsn  | replay_lsn | write_lag | flush_
lag | replay_lag | sync_priority | sync_state |          reply_time
------+----------+-----------+---------------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------+------------+------------+-----------+-------
----+------------+---------------+------------+-------------------------------
 2663 |    16445 | xxx | test_subscription | xxx |                 |       44270 | 2024-09-20 19:19:29.591677+09 |              | streaming | 2/2C0000D8 | 2/2C0000D8 | 2/2C0000D8 | 2/2C0000D8 |           |
    |            |             0 | async      | 2024-09-20 19:19:59.739753+09

Testing

サブスクライバでサブスクリプションを無効化する。

alter subscription test_subscription disable;

パブリッシャでwalを600MBほど生成する

DO $$
DECLARE
    i INTEGER;
BEGIN
    FOR i IN 1..10000 LOOP
        INSERT INTO test.test_publication_table (data) VALUES (repeat('test', 100));
    END LOOP;
END
$$;

1000000レコード作成する、1レコードおよそ420byteあった。

SELECT
    pg_column_size(id) +
    pg_column_size(data) AS total_size
FROM test.test_publication_table
WHERE id = 'xxx';
 total_size
------------
        420

レプリケーションスロットはスタンバイがwal segmentを受信するまでプライマリがwal segmentを削除しないようにする仕組みなので、レプリケーションを再開しない限りwalは増え続ける。そのため、サブスクライバとの接続断が続いた場合にwal diskが枯渇する可能性がある。

SELECT
    slot_name,
    database,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS replication_slot_size
FROM
    pg_replication_slots;
         slot_name         | database | replication_slot_size
---------------------------+----------+-----------------------
 test_subscription | test    | 606 MB

レプリケーションスロットが存在する場合、スロットが参照しているWALファイルは削除されないため、max_wal_sizeの設定値にも依存しない。

レプリケーションの再開

サブスクリプションを有効化する。

alter subscription test_subscription enable;

10secほどでスロットのWALは転送された。

SELECT
    slot_name,
    database,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS replication_slot_size
FROM
    pg_replication_slots;
         slot_name         | database | replication_slot_size
---------------------------+----------+-----------------------
 test_subscription | xxx    | 2778 kB