PostgreSQL Streaming Replication
Join Over 1,000 Engineers & Get New Episodes Weekly!
In this tutorial, we demonstrate how to set up a hot standby replica of your PostgreSQL database cluster. This replica can accept read-only queries and be promoted as a new primary.
# Install initial PostgreSQL 10 cluster and verify it exists
sudo pg_lsclusters
# create a second postgres cluster
sudo pg_createcluster 10 replica1
sudo pg_ctlcluster 10 replica1 status
sudo systemctl status postgresql@10-main
# create archive directories for both clusters
sudo -H -u postgres mkdir /var/lib/postgresql/pg_log_archive/main
sudo -H -u postgres mkdir /var/lib/postgresql/pg_log_archive/replica1
## Configure Main Cluster (Primary / Master) ###################################################
# edit configuration file
sudo nano /etc/postgresql/10/main/postgresql.conf
wal_level = replica
wal_log_hints = on
archive_mode = on # (change requires restart)
archive_command = 'test ! -f /var/lib/postgresql/pg_log_archive/main/%f && cp %p /var/lib/postgresql/pg_log_archive/main/%f'
max_wal_senders = 10
wal_keep_segments = 64
hot_standby = on
# edit host based access file
sudo nano /etc/postgresql/10/main/pg_hba.conf
local replication rep_user trust # DO NOT USE. Configure your own connection and authentication information
# create replication user
sudo -H -u postgres psql -c "CREATE USER rep_user WITH replication;"
# restart the main cluster
sudo systemctl restart postgresql@10-main
## Configure Replica1 Cluster ###################################################################
# stop replica1 cluster
sudo systemctl stop postgresql@10-replica1
# edit configuration file
sudo nano /etc/postgresql/10/replica1/postgresql.conf
wal_level = replica
wal_log_hints = on
archive_mode = on # (change requires restart)
archive_command = 'test ! -f /var/lib/postgresql/pg_log_archive/replica1/%f && cp %p /var/lib/postgresql/pg_log_archive/replica1/%f'
max_wal_senders = 10
wal_keep_segments = 64
hot_standby = on
# edit host based access file
sudo nano /etc/postgresql/10/replica1/pg_hba.conf
local replication rep_user trust
## Setup Replica1 Cluster Replication ###########################################################
# remove replica1 existing database files
sudo su - postgres
rm -rf /var/lib/postgresql/10/replica1
# sync replica1 with main cluster
pg_basebackup -D /var/lib/postgresql/10/replica1 -U rep_user -w -P -R # -X stream
# configure recovery.conf
nano /var/lib/postgresql/10/replica1/recovery.conf
restore_command = 'cp /var/lib/postgresql/pg_log_archive/replica1/%f %p'
recovery_target_timeline = 'latest'
standby_mode = 'on'
primary_conninfo = 'user=rep_user passfile=''/var/lib/postgresql/.pgpass'' host''/var/run/postgresql'' port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres target_session_attrs=any'
archive_cleanup_command = 'pg_archivecleanup /var/lib/postgresql/pg_log_archive/replica1 %r'
# start replica cluster and verify in sync
sudo pg_ctlcluster 10 replica1 start
tail -n 100 /var/log/postgresql/postgresql-10-replica1.log
## Verify Replica1 Cluster In Sync #############################################################
# create database with some data
sudo su - postgres
psql -c "create database test;" -p 5432
psql test -c "
create table posts (
id integer,
title character varying(100),
content text,
published_at timestamp without time zone,
type character varying(100)
);
insert into posts (id, title, content, published_at, type) values
(100, 'Intro to SQL', 'Epic SQL Content', '2018-01-01', 'SQL'),
(101, 'Intro to PostgreSQL', 'PostgreSQL is awesome!', now(), 'PostgreSQL');
"
# verify data has been replicated on replica1
psql test -c "select * from posts;" -p 5433
# stop main cluster (simulate failure condition)
sudo systemctl status postgresql@10-main
# promote replica1
sudo pg_ctlcluster 10 replica1 promote
# verify replica1 is now a master / primary cluster
tail -n 100 /var/log/postgresql/postgresql-10-replica1.log
psql test -c "insert into posts (id, title, content, type) values
(102, 'Intro to SQL Where Clause', 'Easy as pie!', 'SQL'),
(103, 'Intro to SQL Order Clause', 'What comes first?', 'SQL');" -p 5433
psql test -c "select * from posts;" -p 5433