ตั้ง PostgreSQL Replication บน VPS

ตั้ง PostgreSQL Replication บน VPS

มิถุนายน 2026 · อ่าน 9 นาที

PostgreSQL Streaming Replication ส่ง WAL (Write-Ahead Log) จาก primary ไปยัง standby server แบบ real-time ทำให้ standby มีข้อมูลล่าช้าไม่กี่มิลลิวินาที ถ้า primary ล่มสามารถ promote standby ขึ้นมาแทนได้รวดเร็ว เป็น approach ที่ production database ส่วนใหญ่ใช้เพื่อลด RTO (Recovery Time Objective) และ RPO (Recovery Point Objective)

สถาปัตยกรรม

ในบทความนี้ใช้ 2 node:

ติดตั้ง PostgreSQL บนทั้งสอง Node

sudo apt update
sudo apt install postgresql postgresql-contrib -y

# ตรวจ version
psql --version
sudo systemctl status postgresql

ตั้งค่า Primary Server

sudo -u postgres psql
-- สร้าง replication user
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'ReplicaPassword123';
\q
sudo nano /etc/postgresql/16/main/postgresql.conf
listen_addresses = '*'
wal_level = replica
max_wal_senders = 5
wal_keep_size = 1GB
hot_standby = on
sudo nano /etc/postgresql/16/main/pg_hba.conf
# เพิ่มที่ท้ายไฟล์
host    replication     replicator      192.168.1.11/32     md5
sudo systemctl restart postgresql

ตั้งค่า Standby Server

# หยุด PostgreSQL บน standby ก่อน
sudo systemctl stop postgresql

# ลบ data directory เดิม
sudo rm -rf /var/lib/postgresql/16/main/*

# Clone จาก primary
sudo -u postgres pg_basebackup -h 192.168.1.10 -U replicator -D /var/lib/postgresql/16/main -Fp -Xs -P -R
# -R สร้าง standby.signal และ primary_conninfo ให้อัตโนมัติ
sudo nano /etc/postgresql/16/main/postgresql.conf
listen_addresses = '*'
hot_standby = on
# อนุญาต read query บน standby
hot_standby_feedback = on
sudo systemctl start postgresql
Tip: pg_basebackup -R จะสร้างไฟล์ standby.signal และ postgresql.auto.conf ที่มี primary_conninfo ให้อัตโนมัติ ไม่ต้องตั้งมือ

ทดสอบ Read Query บน Standby

# Standby รับ read-only query ได้
sudo -u postgres psql -c "SELECT now(), pg_is_in_recovery();"
# pg_is_in_recovery = true แสดงว่าเป็น standby

# ทดสอบ: สร้าง table บน primary แล้วดูว่า standby เห็นไหม
# บน primary:
sudo -u postgres psql -c "CREATE TABLE test_repl (id serial, msg text);"
sudo -u postgres psql -c "INSERT INTO test_repl(msg) VALUES ('hello from primary');"
# บน standby:
sudo -u postgres psql -c "SELECT * FROM test_repl;"

ตรวจสอบว่า PostgreSQL Replication ทำงานถูกต้อง

# ตรวจ replication status จาก primary
sudo -u postgres psql -c "SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn FROM pg_stat_replication;"

# ดู replication lag (ควรน้อยมากถ้า network ดี)
sudo -u postgres psql -c "SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay;"

# ตรวจ standby mode
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"
Tip: ค่า replication_delay ควรไม่เกิน 1-2 วินาทีสำหรับ local network ถ้าเกิน 10 วินาทีให้ตรวจ network bandwidth และ I/O load บน primary

แก้ปัญหาที่พบบ่อย

Error: "could not connect to the primary server"

ตรวจ primary_conninfo และ pg_hba.conf:

cat /var/lib/postgresql/16/main/postgresql.auto.conf
# ตรวจ primary_conninfo มี IP ถูก และ password ถูก

# ตรวจ pg_hba.conf บน primary อนุญาต standby IP หรือไม่
grep replicator /etc/postgresql/16/main/pg_hba.conf
sudo systemctl reload postgresql  # บน primary

Standby หยุด sync (replication slot ค้าง)

ถ้าใช้ replication slot และ standby หายไปนาน wal_keep_size อาจไม่พอ:

# ตรวจ slot ที่ค้างอยู่
sudo -u postgres psql -c "SELECT * FROM pg_replication_slots;"
# ถ้า standby ออกจากระบบถาวร ให้ drop slot
sudo -u postgres psql -c "SELECT pg_drop_replication_slot('slot_name');"

Standby ล้าหลังมาก (replication lag สูง)

เพิ่ม wal_sender_timeout และตรวจ network:

sudo nano /etc/postgresql/16/main/postgresql.conf
wal_sender_timeout = 60s
# ตรวจ bandwidth ระหว่าง primary และ standby
iperf3 -s  # บน standby
iperf3 -c STANDBY-IP  # บน primary

Promote standby เป็น primary (manual failover)

# บน standby เมื่อ primary ล่ม
sudo -u postgres pg_ctl promote -D /var/lib/postgresql/16/main
# ตรวจว่า promote สำเร็จ
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"
# ต้องได้ false

คำถามที่พบบ่อย

Streaming Replication กับ Logical Replication ต่างกันอย่างไร?

Streaming Replication copy WAL ทั้งหมด (physical copy) standby ต้องเป็น PostgreSQL version เดียวกัน Logical Replication copy เฉพาะ table ที่กำหนด รองรับข้าม version และ cross-platform ใช้สำหรับ selective sync หรือ zero-downtime migration

Standby สามารถรับ read query ได้ไหม?

ได้ถ้าตั้ง hot_standby = on application สามารถ route read query ไปยัง standby ช่วยลด load บน primary ได้ แต่ standby ไม่รับ write query เลย ต้องส่งทุก write ไปที่ primary เท่านั้น

ควรใช้ Patroni ด้วยไหม?

Patroni ทำ automatic failover โดยไม่ต้องรัน pg_ctl promote เอง เหมาะสำหรับ production ที่ต้องการ zero-downtime failover Patroni ใช้ etcd หรือ Consul เป็น distributed store เพื่อตัดสินใจ leader election สำหรับการใช้งาน 2 node basic ทำ manual failover ก็เพียงพอ