Начиная с версии 10, все необходимые настройки уже присутствуют по умолчанию:
Создадим автономную резервную копию. В качестве каталога для сохранения сразу используем PGDATA резервного сервера. Ключ -R создаст заготовку управляющего файла recovery.conf.
postgres$ rm -rf /usr/local/pgsql2/data/*
postgres$ pg_basebackup --pgdata=/usr/local/pgsql2/data -R
Резервный сервер уже предварительно собран и установлен.
Мы собираемся запустить второй сервер одновременно с основным на одной машине, поэтому в настройках необходимо поменять порт:
postgres$ echo 'port = 5433' >> /usr/local/pgsql2/data/postgresql.auto.conf
И добавим параметр горячего резерва, чтобы реплика принимала запросы на чтение:
postgres$ echo 'hot_standby = on' >> /usr/local/pgsql2/data/postgresql.auto.conf
Заготовка для recovery.conf была подготовлена утилитой pg_basebackup, и она нас устраивает:
postgres$ cat /usr/local/pgsql2/data/recovery.conf
standby_mode = 'on' primary_conninfo = 'user=postgres passfile=''/home/postgres/.pgpass'' port=5432 sslmode=disable sslcompression=1 target_session_attrs=any'
Можно запускать сервер.
postgres$ pg_ctl -w -l /home/postgres/logfile2 -D /usr/local/pgsql2/data start
waiting for server to start.... done server started
В приведенной команде мы явно указываем расположение каталога с данными кластера. Для удобства в виртуальной машине есть команды "1" и "2", которые переключают окружение на первый и на второй сервер соответственно.
Посмотрим на процессы реплики.
postgres$ ps -o pid,command --ppid `head -n 1 /usr/local/pgsql2/data/postmaster.pid`
PID COMMAND 4316 postgres: startup process waiting for 000000010000000000000008 4317 postgres: checkpointer process 4318 postgres: writer process 4319 postgres: stats collector process 4320 postgres: wal receiver process
Процесс wal receiver принимает поток журнальных записей, процесс startup применяет изменения.
И сравним с процессами мастера.
postgres$ ps -o pid,command --ppid `head -n 1 /usr/local/pgsql/data/postmaster.pid`
PID COMMAND 4209 postgres: postgres postgres [local] idle 4321 postgres: wal sender process postgres [local] idle 22611 postgres: checkpointer process 22612 postgres: writer process 22613 postgres: wal writer process 22614 postgres: autovacuum launcher process 22615 postgres: stats collector process 22616 postgres: bgworker: logical replication launcher
Здесь добавился процесс wal sender.
Состояние репликации можно смотреть в специальном представлении на мастере:
postgres$ psql -p 5432
=> SELECT * FROM pg_stat_replication \gx
-[ RECORD 1 ]----+----------------------------- pid | 4321 usesysid | 10 usename | postgres application_name | walreceiver client_addr | client_hostname | client_port | -1 backend_start | 2019-03-31 15:26:16.48161+03 backend_xmin | state | streaming sent_lsn | 0/8000000 write_lsn | 0/8000000 flush_lsn | 0/8000000 replay_lsn | 0/8000000 write_lag | 00:00:00.101554 flush_lag | 00:00:00.101554 replay_lag | 00:00:00.101554 sync_priority | 0 sync_state | async
Выполним несколько команд на мастере:
=> CREATE DATABASE replica_overview;
CREATE DATABASE
=> \c replica_overview;
You are now connected to database "replica_overview" as user "postgres".
=> CREATE TABLE test(id integer PRIMARY KEY, descr text);
CREATE TABLE
Проверим реплику:
postgres$ psql -p 5433 -d replica_overview
=> SELECT * FROM test;
id | descr ----+------- (0 rows)
=> INSERT INTO test VALUES (1, 'Раз');
INSERT 0 1
=> SELECT * FROM test;
id | descr ----+------- 1 | Раз (1 row)
При этом изменения на реплике не допускаются:
=> INSERT INTO test VALUES (2, 'Два');
ERROR: cannot execute INSERT in a read-only transaction
Теперь переведем реплику из режима восстановления в обычный режим. Таким образом, получим два самостоятельных, никак не связанных друг с другом сервера.
postgres$ pg_ctl -w -D /usr/local/pgsql2/data promote
waiting for server to promote.... done server promoted
=> INSERT INTO test VALUES (2, 'Два');
INSERT 0 1
Далее мы хотим настроить между серверами логическую репликацию. Для этого нам понадобится дополнительная информация в журнале.
=> ALTER SYSTEM SET wal_level = logical;
ALTER SYSTEM
postgres$ pg_ctl -w -l /home/postgres/logfile -D /usr/local/pgsql/data restart
waiting for server to shut down.... done server stopped waiting for server to start.... done server started
На первом сервере создаем публикацию:
postgres$ psql -d replica_overview
=> CREATE PUBLICATION test_pub FOR TABLE test;
CREATE PUBLICATION
=> \dRp+
Publication test_pub Owner | All tables | Inserts | Updates | Deletes ----------+------------+---------+---------+--------- postgres | f | t | t | t Tables: "public.test"
На втором сервере подписываемся на эту публикацию (отключаем первоначальное копирование данных):
=> CREATE SUBSCRIPTION test_sub CONNECTION 'host=localhost port=5432 user=postgres dbname=replica_overview' PUBLICATION test_pub WITH (copy_data = false);
NOTICE: created replication slot "test_sub" on publisher CREATE SUBSCRIPTION
=> \dRs
List of subscriptions Name | Owner | Enabled | Publication ----------+----------+---------+------------- test_sub | postgres | t | {test_pub} (1 row)
=> INSERT INTO test VALUES (3, 'Три');
INSERT 0 1
=> SELECT * FROM test;
id | descr ----+------- 1 | Раз 2 | Два 3 | Три (3 rows)
Состояние подписки можно посмотреть в представлении:
=> SELECT * FROM pg_stat_subscription \gx
-[ RECORD 1 ]---------+------------------------------ subid | 24576 subname | test_sub pid | 4789 relid | received_lsn | 0/802E0DC last_msg_send_time | 2019-03-31 15:26:20.175076+03 last_msg_receipt_time | 2019-03-31 15:26:20.175447+03 latest_end_lsn | 0/802E0DC latest_end_time | 2019-03-31 15:26:20.175076+03
К процессам сервера добавился logical replication worker (его номер указан в pg_stat_subscription.pid):
postgres$ ps -o pid,command --ppid `head -n 1 /usr/local/pgsql2/data/postmaster.pid`
PID COMMAND 4317 postgres: checkpointer process 4318 postgres: writer process 4319 postgres: stats collector process 4543 postgres: postgres replica_overview [local] idle 4642 postgres: wal writer process 4643 postgres: autovacuum launcher process 4644 postgres: bgworker: logical replication launcher 4789 postgres: bgworker: logical replication worker for subscription 24576
Если репликация больше не нужна, надо аккуратно удалить подписку - иначе на публикующем сервере останется открытым репликационный слот.
=> DROP SUBSCRIPTION test_sub;
NOTICE: dropped replication slot "test_sub" on publisher DROP SUBSCRIPTION
Конец демонстрации.