PostgreSQL Yedekleme ve Eş Zamanlı Replikasyon: pg_basebackup, WAL Arşivleme ve Streaming Replication
"Yedek alıyoruz" ile "yedekten dönebiliyoruz" arasında dağlar kadar fark var. Birçok kurum, bir kriz anında yedeklerinin bozuk veya eksik olduğunu fark eder — o zaman iş işten geçmiş olur.
PostgreSQL, sağlam bir yedekleme altyapısı için ihtiyacınız olan her şeyi sunar. Bu yazıda üç katmanlı bir strateji kuruyoruz: anlık yedek, sürekli WAL arşivleme ve gerçek zamanlı standby.
Yedekleme Stratejisinin Üç Katmanı
| Katman | Yöntem | RPO | RTO |
|---|---|---|---|
| 1. Anlık yedek | pg_basebackup | Saatler | Dakikalar-saatler |
| 2. Sürekli arşiv | WAL arşivleme + base backup | Dakikalar | Dakikalar |
| 3. Canlı standby | Streaming replication | Saniyeler | Saniyeler |
RPO (Recovery Point Objective): Ne kadar veri kaybedebilirsiniz?
RTO (Recovery Time Objective): Ne kadar sürede ayağa kalkmalısınız?
Katman 1: pg_basebackup ile Anlık Yedek
En basit yöntem. Tüm cluster dosyalarını kopyalar.
# Temel kullanım — sıkıştırılmış tar arşivi
pg_basebackup \
--host=localhost \
--username=replicator \
--pgdata=/yedek/pg_base_$(date +%Y%m%d) \
--format=tar \
--compress=9 \
--checkpoint=fast \
--progress
# Cron ile günlük yedek (her gece 02:00)
0 2 * * * pg_basebackup -h localhost -U replicator \
-D /yedek/pg_$(date +\%Y\%m\%d) -Ft -z -Xstream -P
Replikasyon kullanıcısı oluştur
CREATE USER replicator REPLICATION LOGIN ENCRYPTED PASSWORD 'güçlü_şifre';
pg_hba.conf'a ekle:
host replication replicator 127.0.0.1/32 scram-sha-256
Yedekten Dönme Testi
Almak kadar dönmek de önemli — her yedek test edilmeli.
# Test ortamına geri yükle
mkdir -p /test/pg_restore
tar -xzf /yedek/pg_20260616/base.tar.gz -C /test/pg_restore
# PostgreSQL'i test portta başlat
postgres -D /test/pg_restore -p 5433 &
# Bağlan ve kontrol et
psql -p 5433 -c "SELECT count(*) FROM kritik_tablo;"
Katman 2: WAL Arşivleme — Dakika Düzeyinde Kurtarma
WAL (Write-Ahead Log), PostgreSQL'in tüm değişiklikleri önce yazdığı günlüktür. Bu dosyaları arşivleyerek herhangi bir dakikaya dönebilirsiniz (Point-in-Time Recovery — PITR).
postgresql.conf Ayarları
wal_level = replica # en az replica olmalı
archive_mode = on
archive_command = 'cp %p /wal-arsiv/%f' # ya da rsync, s3 vb.
archive_timeout = 300 # 5 dakikada bir arşivle (boşta bile)
Daha güvenli bir archive_command (başarısız olursa yeniden dener):
archive_command = 'test ! -f /wal-arsiv/%f && cp %p /wal-arsiv/%f'
Uzak sunucuya rsync ile:
archive_command = 'rsync -a %p yedek-sunucu:/wal-arsiv/%f'
PITR — Belirli Bir Zamana Dönme
Diyelim ki saat 14:32'de bir tablo yanlışlıkla silindi. Tam o ana dönebilirsiniz:
# 1. Son base backup'ı restore et
tar -xzf /yedek/pg_20260616/base.tar.gz -C /data/pg_restore
# 2. recovery.conf (PG 12 öncesi) veya postgresql.conf'a ekle
cat >> /data/pg_restore/postgresql.conf << 'EOF'
restore_command = 'cp /wal-arsiv/%f %p'
recovery_target_time = '2026-06-16 14:31:59'
recovery_target_action = 'promote'
EOF
# 3. recovery.signal dosyası oluştur (PG 12+)
touch /data/pg_restore/recovery.signal
# 4. Başlat
pg_ctl start -D /data/pg_restore
PostgreSQL WAL dosyalarını sırayla uygulayarak tam olarak 14:31:59'daki duruma getirir.
Katman 3: Streaming Replication — Sıfıra Yakın Veri Kaybı
Primary → Standby arasında gerçek zamanlı veri akışı. Primary çökerse standby saniyeler içinde devreye girer.
Primary Ayarları (postgresql.conf)
wal_level = replica
max_wal_senders = 3 # aynı anda kaç standby bağlanabilir
wal_keep_size = 1GB # standby geride kalırsa buffer
hot_standby = on # standby read-only sorguları kabul etsin
synchronous_commit = on # senkron replikasyon (veri kaybı sıfır, biraz daha yavaş)
pg_hba.conf'a standby izni:
host replication replicator STANDBY_IP/32 scram-sha-256
Standby Kurulumu
# Primary'den base backup al
pg_basebackup \
--host=PRIMARY_IP \
--username=replicator \
--pgdata=/data/standby \
--wal-method=stream \
--progress
# Standby sinyali
touch /data/standby/standby.signal
# postgresql.conf'ta primary bağlantısı
echo "primary_conninfo = 'host=PRIMARY_IP user=replicator password=şifre'" \
>> /data/standby/postgresql.conf
# Başlat
pg_ctl start -D /data/standby
Replikasyon Durumunu İzle
-- Primary'de: standby'lar bağlı mı, geride mi?
SELECT
application_name,
state,
sent_lsn,
replay_lsn,
(sent_lsn - replay_lsn)::text AS gerideki_bytes,
sync_state
FROM pg_stat_replication;
-- Standby'da: ne kadar geride?
SELECT
now() - pg_last_xact_replay_timestamp() AS replikasyon_gecikmesi;
Failover — Standby'ı Promote Et
Primary çöktüğünde:
# Standby'ı primary olarak yükselt
pg_ctl promote -D /data/standby
# Ya da SQL ile
SELECT pg_promote();
Uygulama bağlantılarını yeni primary'ye (eski standby) yönlendirin.
Sektördeki En İyi Araçlar
| Araç | Kullanım | Ücreti |
|---|---|---|
| Barman | Merkezi WAL arşivleme, çoklu cluster yönetimi | Ücretsiz |
| pgBackRest | Paralel yedek, S3 entegrasyonu, delta backup | Ücretsiz |
| repmgr | Otomatik failover yönetimi | Ücretsiz |
| Patroni | Kubernetes-native HA, etcd/consul ile | Ücretsiz |
Production ortamlar için pgBackRest + Patroni kombinasyonunu öneriyoruz.
Yedekleme Sağlık Kontrol Listesi
Yedek altyapınızı kurarken şu soruların yanıtı "evet" olmalı:
- Her gece base backup alınıyor mu?
- WAL arşivleme aktif ve boşluk yok mu? (
archive_statuskontrol et) - Yedekler farklı bir lokasyonda (off-site) mı?
- Aylık restore testi yapılıyor mu?
- Standby replikasyon gecikmesi izleniyor mu?
- Failover prosedürü test edildi mi?
PostgreSQL yedekleme altyapısı kurulumu, mevcut yapının PITR'a geçişi veya replikasyon sorunlarınız için teknik görüşme talep edebilirsiniz.