I wanted to setup a PostgreSQL database replication where you have one read/write master, and one or more readonly slaves, pretty much what has been possible with MySQL, too. As always, on FreeBSD that's fairly easy:
# make -C /usr/ports/databases/postgresql10-server install clean # make -C /usr/ports/databases/postgresql10-contrib install cleanFor the server and client, I always choose the INTDATE, OPTIMIZED_CFLAGS, SSL, TZDATA, and XML options
# sysrc postgresql_enable=YES
# pw usermod postgres -d /tank/postgres -m # rm -v /tank/postgres/.[a-z]*At least make sure that on all servers the home directory is the same
# service postgresql initdb
listen_addresses = 'localhost, 10.0.0.10'In this case, 10.0.0.10 is the ip address that the slave database servers will connect to. As an alternative you could have your PostgreSQL master server listen on all configured ip addresses:
listen_addresses = '*'
service postgresql start
# psql postgres postgres Password for user postgres: psql (10.0) Type "help" for help. postgres=# ALTER USER postgres PASSWORD 'secret'; ALTER ROLE postgres=#
postgres=# CREATE USER replicator REPLICATION PASSWORD 'moarsecret'; CREATE ROLE postgres=# SELECT * FROM pg_create_physical_replication_slot('server2'); slot_name | lsn -----------+----- server2 | (1 row) postgres=# \q #
# TYPE DATABASE USER ADDRESS METHOD local all all md5 host all all 10.0.2.0/24 md5 host replication replicator 10.0.0.11/32 md5This opens connections to all databases for all users from either the master server itself of from the subnet 10.0.2.0/24. Additionally, the user replicator can connect from the host 10.0.0.11, which will be a slave server, but is just allowed to do streaming replication due to the replication entry in the database field of pg_hba.conf
# psql -c "SELECT pg_reload_conf()" postgres postgres Password for user postgres: pg_reload_conf ---------------- t (1 row) #
# su - postgres # pg_basebackup -D /tank/postgres/data10 -R -v -P -S server2 -h 192.168.255.193 -U replicator Password: pg_basebackup: initiating base backup, waiting for checkpoint to complete pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 0/C5000028 on timeline 1 pg_basebackup: starting background WAL receiver 37642/37642 kB (100%), 1/1 tablespace pg_basebackup: write-ahead log end point: 0/C5000130 pg_basebackup: waiting for background process to finish streaming ... pg_basebackup: base backup completedThe above output is from a small live database, thus actual values may vary
listen_addresses = 'localhost, 10.0.0.11'
# service postgresql start
# psql -c "SELECT * FROM pg_replication_slots" -c "SELECT * FROM pg_stat_replication" postgres postgres Password for user postgres: slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn -----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+--------------------- server2 | | physical | | | f | t | 95670 | | | 0/C8000CF0 | (1 row) 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 -------+----------+------------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------+------------+------------+-----------+-----------+------------+---------------+------------ 95670 | 550154 | replicator | walreceiver | 10.0.0.11 | | 33488 | 2017-11-05 12:56:57.616059+01 | | streaming | 0/C8000CF0 | 0/C8000CF0 | 0/C8000CF0 | 0/C8000CF0 | | | | 0 | async (1 row)There should be one entry for each slave database in pg_stat_replication. restart_lsn and replay_lsn should match. replay_lag should be null.
# psql -c "SELECT * FROM pg_stat_wal_receiver" postgres postgres Password for user postgres: pid | status | receive_start_lsn | receive_start_tli | received_lsn | received_tli | last_msg_send_time | last_msg_receipt_time | latest_end_lsn | latest_end_time | slot_name | conninfo -----+-----------+-------------------+-------------------+--------------+--------------+-------------------------------+-------------------------------+----------------+-------------------------------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 787 | streaming | 0/C8000000 | 1 | 0/C8000CF0 | 1 | 2017-11-05 13:14:51.049779+01 | 2017-11-05 13:14:51.116915+01 | 0/C8000CF0 | 2017-11-05 13:10:50.248827+01 | server1 | user=replicator password=******** dbname=replication host=10.0.0.11 port=5432 fallback_application_name=walreceiver sslmode=prefer sslcompression=1 target_session_attrs=any (1 row)latest_end_lsn should match replay_lsn.
# psql -c "SELECT * FROM pg_drop_replication_slot('server3')" postgres postgres Password for user postgres: pg_drop_replication_slot -------------------------- (1 row)If you forget to drop a replication slot for a non-existing server, then the master database will keep write-ahead-logs (WAL files) forever, causing /tank/postgres/data10/pg_wal to grow.