Kodeloka
  1. Kodeloka
  2. Kelas PostgreSQL
  3. Materi

6 · Skala · Modul 8 dari 12

Replikasi, Backup & Point-in-Time Recovery

Menyiapkan replika baca, memilih antara replikasi fisik dan logis, dan membangun strategi backup yang benar-benar bisa dipulihkan.

Dua Jenis Replikasi

Fisik (streaming)Logis
Yang direplikasiBlok WAL apa adanyaPerubahan baris
CakupanSeluruh instansiBisa per tabel
Beda versi PostgreSQLTidak bisaBisa
Replika bisa ditulisiTidakYa
Dipakai untukHA, replika bacaUpgrade tanpa henti, integrasi data

Replikasi Streaming

-- Di primer
CREATE ROLE replikator WITH REPLICATION LOGIN PASSWORD 'rahasia';

-- postgresql.conf
wal_level = replica
max_wal_senders = 10

-- Di replika
pg_basebackup -h primer -U replikator -D /var/lib/postgresql/data \
    -Fp -Xs -P -R -C -S replika1
-- Memantau dari primer
SELECT client_addr, state, sent_lsn, replay_lsn,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS byte_tertinggal
FROM pg_stat_replication;

-- Dari replika
SELECT now() - pg_last_xact_replay_timestamp() AS lag_waktu;
⚠️ Replication slot: penyelamat sekaligus jebakan

Slot memastikan primer tidak membuang WAL sebelum replika sempat menerimanya — tanpa slot, replika yang tertinggal terlalu jauh akan rusak permanen. Tetapi bila replika mati dan slotnya tidak dibersihkan, primer akan menyimpan WAL selamanya sampai disk penuh dan basis data berhenti melayani.

Selalu pantau pg_replication_slots dan pertimbangkan max_slot_wal_keep_size sebagai pengaman.

Konflik pada Replika Baca

🚫 Kueri panjang di replika bisa dibatalkan paksa

Ketika primer mem-vacuum baris yang masih dibaca kueri di replika, akan terjadi konflik. Bawaannya, replika membatalkan kueri tersebut setelah max_standby_streaming_delay.

-- Beri kueri lebih banyak waktu (menambah lag)
max_standby_streaming_delay = 300s

-- Atau beri tahu primer agar menunda vacuum
hot_standby_feedback = on
-- ⚠️ Konsekuensinya: kueri panjang di replika kini menyebabkan
--    bloat di PRIMER. Ini pertukaran yang harus disadari.

Replikasi Logis

-- Di penerbit
wal_level = logical
CREATE PUBLICATION pub_pesanan FOR TABLE pesanan, item_pesanan;

-- Di pelanggan
CREATE SUBSCRIPTION sub_pesanan
  CONNECTION 'host=primer dbname=toko user=replikator password=rahasia'
  PUBLICATION pub_pesanan;
💡 Kegunaan paling berharga: upgrade mayor tanpa henti

Replikasi logis bisa berjalan antar versi PostgreSQL yang berbeda. Alurnya: siapkan instansi versi baru sebagai pelanggan, biarkan tersinkron sepenuhnya, lalu alihkan aplikasi. Waktu henti berkurang dari berjam-jam menjadi hitungan detik.

⚠️ Batasan replikasi logis

Ia tidak mereplikasi perubahan skema (DDL) maupun urutan (sequence). Tabel yang direplikasi wajib punya kunci utama atau REPLICA IDENTITY FULL, kalau tidak UPDATE dan DELETE akan gagal.

Backup: Tiga Tingkat

-- 1. Logis — fleksibel, lambat untuk basis data besar
pg_dump -Fc -j 4 -d toko -f toko.dump
pg_restore -d toko_baru -j 4 toko.dump

-- 2. Fisik — cepat, seluruh kluster
pg_basebackup -D /backup/basis -Ft -z -Xs -P

-- 3. PITR — fisik + arsip WAL berkelanjutan
archive_mode = on
archive_command = 'pgbackrest --stanza=produksi archive-push %p'

pgbackrest --stanza=produksi \
  --type=time --target="2026-07-28 14:25:00+07" \
  --delta restore
📌 Pakai pgBackRest atau Barman, jangan skrip sendiri

Skrip archive_command buatan sendiri terkenal rapuh: menangani kegagalan sebagian, verifikasi, retensi, dan backup paralel jauh lebih rumit daripada yang terlihat. pgBackRest menyediakan backup inkremental, kompresi, verifikasi checksum, retensi otomatis, dan pemulihan paralel — semuanya sudah teruji di produksi.

🚫 Backup yang belum pernah dipulihkan bukan backup

Ini bukan slogan. Kegagalan yang berulang kali terjadi di banyak organisasi: backup berjalan rapi selama bertahun-tahun, lalu saat benar-benar dibutuhkan ternyata arsip WAL tidak lengkap, atau prosedur pemulihannya tidak pernah dicoba dan gagal di tengah krisis.

Jadwalkan uji pemulihan berkala ke server terpisah, dan catat berapa lama prosesnya. Angka itulah RTO Anda yang sesungguhnya, bukan yang tertulis di dokumen.