PostgreSQL yedekleme rehberi: pg_dump'tan zamana dönük kurtarmaya (PITR)
Mantıksal yedek, fiziksel yedek, WAL arşivleme ve belirli bir saniyeye geri dönme. Yıllar önce verdiğim PostgreSQL eğitim notlarını güncel sürümlere göre baştan yazdım.
Yıllar önce PostgreSQL eğitimleri verirken yedekleme konusu her zaman en çok soru alan bölümdü. O günkü lab notlarım PostgreSQL 9.0 dönemine aitti; recovery.conf, pg_start_backup(), pg_xlog dizini... Bunların bir kısmı artık yok, bir kısmının adı değişti. Bu yazıda aynı konuyu güncel sürümlere (PostgreSQL 16-18) göre anlatıyorum.
İki tür yedek
- Mantıksal yedek (pg_dump): Veritabanını SQL komutları ya da özel bir arşiv olarak dışarı alır. Taşınabilir, sürümler arası geçişte kullanılabilir; ama yalnızca alındığı ana döner.
- Fiziksel yedek (pg_basebackup + WAL): Veri dizininin kopyası ve sonrasındaki tüm değişikliklerin günlüğü (WAL). Belirli bir saniyeye geri dönmeyi (PITR) mümkün kılar.
1. pg_dump ile mantıksal yedek
Düz SQL olarak:
pg_dump -d satisdb > satisdb.sql
psql -d satisdb_yeni -1 < satisdb.sql # -1: tek transaction içinde yükle
Pratikte en kullanışlısı custom (-Fc) ya da directory (-Fd) formatıdır; sıkıştırılmış olur ve geri yüklerken seçici davranabilirsiniz:
pg_dump -Fc -d satisdb -f satisdb.dump
pg_restore -d satisdb_yeni -j 4 satisdb.dump # 4 paralel iş
# Büyük veritabanlarında dump'ı da paralel almak için:
pg_dump -Fd -j 4 -d satisdb -f satisdb_dizin/
Unutulan nokta: roller ve tablespace'ler pg_dump ile gelmez. Onları ayrıca alın:
pg_dumpall --globals-only > globals.sql
Geri yüklemeden sonra planlayıcının doğru karar vermesi için istatistikleri toplayın: ANALYZE;
2. WAL arşivleme ve baz yedek
postgresql.conf içinde:
wal_level = replica # PostgreSQL 10'dan beri varsayılan
archive_mode = on
archive_command = 'test ! -f /arsiv/wal/%f && cp %p /arsiv/wal/%f'
archive_mode değişikliği için sunucuyu yeniden başlatmak gerekir. test ! -f kısmı, aynı adlı bir dosyanın üzerine yanlışlıkla yazılmasını engeller.
Eskiden SELECT pg_start_backup(...) deyip tar ile veri dizinini kopyalar, sonra pg_stop_backup() derdik. Bugün tek komut yeterli:
pg_basebackup -D /arsiv/base/2026-10-20 -Ft -z -P
Not: Hâlâ elle yöntemi kullanmak isteyenler için fonksiyonların adı PostgreSQL 15'te pg_backup_start() / pg_backup_stop() olarak değişti.
3. Belirli bir ana geri dönmek (PITR)
Diyelim ki saat 14:32'de biri yanlışlıkla bir tabloyu sildi. 14:31'e dönmek için:
- Sunucuyu durdurun ve mevcut veri dizinini (ne olur ne olmaz) kenara kopyalayın.
- Veri dizinini boşaltıp baz yedeği açın.
postgresql.conf(ya dapostgresql.auto.conf) içine kurtarma ayarlarını yazın:
restore_command = 'cp /arsiv/wal/%f %p'
recovery_target_time = '2026-10-20 14:31:00+03'
recovery_target_action = 'promote'
- Veri dizininde boş bir
recovery.signaldosyası oluşturun ve sunucuyu başlatın.
PostgreSQL 12 ile recovery.conf dosyası kaldırıldı; eski notlarda gördüğünüz bu dosyanın yerini yukarıdaki ayarlar ve recovery.signal aldı. Eski pg_xlog dizini de PostgreSQL 10'dan beri pg_wal adını taşıyor.
4. Yeni: artımlı (incremental) yedek
PostgreSQL 17 ile pg_basebackup artımlı yedek alabiliyor. summarize_wal = on ayarıyla, bir önceki yedekten bu yana değişen blokları alıp sonra pg_combinebackup ile tam yedeğe dönüştürebilirsiniz. Büyük veritabanlarında yedek süresini ciddi şekilde kısaltır.
Altın kurallar
- Denenmemiş yedek, yedek değildir. Ayda bir başka bir sunucuya geri yükleme provası yapın.
- Yedekleri veritabanı sunucusundan farklı bir diskte, tercihen farklı bir lokasyonda tutun.
- Daha büyük ortamlarda pgBackRest ya da Barman gibi araçlar saklama süresi, sıkıştırma ve doğrulama işlerini sizin yerinize üstlenir.
Yorumlar (0)