pgBackRest ile hata öncesine dönüşü planlamak
Yanlış veritabanında çalıştırılan bir migration komutunun birkaç tabloyu sildiğini düşün. Bir VPS üzerindeki PostgreSQL kümesini hata öncesine döndürmek için uygun bir fiziksel yedek ve o noktaya kadar gerekli WAL kayıtları gerekir. pgBackRest ile PostgreSQL yedekleme ve PITR bu iki parçayı bir kurtarma akışında birleştirir.
Bu rehberde pgBackRest deposunu hazırlayacak, WAL arşivlemeyi etkinleştirecek, tam ve diferansiyel yedekleri zamanlayacak ve izole bir ortamda geri dönüş yapacağız. Komutlar PostgreSQL 17 kullanan Debian/Ubuntu örneğine aittir; yollar, paket sürümü ve küme adı uygulama öncesinde doğrulanmalıdır.
PITR bütün fiziksel kümeyi seçilen geçmiş duruma döndürür. Hatalı işlemin yanında hedef zamandan sonraki geçerli işlemler de geri yüklenen kopyada bulunmaz. Üretime geçiş planında bu işlemlerin nasıl uzlaştırılacağını ve uygulama yazmalarının ne zaman durdurulacağını belirle.
Temel kavramlar: yedek, WAL ve kurtarma hedefi
WAL, PostgreSQL’in veri dosyalarına uyguladığı değişiklikleri yeniden oynatmasını sağlayan kayıtlardır. Kalıcı veri sayfaları yazılmadan önce ilgili WAL kayıtları kalıcı depolamaya aktarılır; her uygulama olayının veya yapılandırma dosyası değişikliğinin WAL’da bulunduğunu varsayma. Fiziksel yedek ve gerekli WAL birlikte tutarlı bir başlangıç sağlar; PostgreSQL ardından hedefe doğru ilerler.
pgBackRest tam, diferansiyel ve artımlı yedekleri, WAL arşivini ve saklama bağımlılıklarını yönetir. Restore komutu dosyaları ve kurtarma ayarlarını hazırlar; WAL kayıtlarını sunucu başladıktan sonra PostgreSQL uygular. Kullanılabilir bir hedef için yedeğin tutarlı hale geldiği nokta hedefi geçmemeli ve gereken WAL zinciri eksiksiz olmalıdır.
Kurtarma süresi veri hacmi, disk ve ağ hızı ile uygulanacak WAL miktarına bağlıdır. Kabul edilebilir veri kaybını RPO, hizmetin geri dönmesi için hedef süreyi RTO olarak kaydet; örnek bir zamanlama bu hedefleri kendiliğinden garanti etmez. Sunucu saatini eşitle ve olay zamanlarını UTC farkıyla sakla.
PostgreSQL 17 için pgBackRest kurulumu
Hangi parçalara ihtiyacımız var?
Örnek, ayrı bir deneme VPS’inde çalışan PostgreSQL 17 main kümesini ve yeni, yerel bir depoyu kullanır. Veri dizini /var/lib/postgresql/17/main, dış yapılandırma dizini /etc/postgresql/17/main kabul edilir; harici tablespace yoktur. Aynı VPS’teki depo veya ikinci disk, tüm VPS’in kaybına karşı bağımsız koruma sağlamaz. Üretimde ayrı bir yedek sunucusu ya da nesne deposu ve bunun geri dönüş testi gerekir.
pgBackRest kurulumu
Dağıtımın veya PostgreSQL paket deposunun, PostgreSQL 17 ile uyumlu pgBackRest paketini kullan. Aşağıdaki paket adı uygun deponun önceden yapılandırıldığını varsayar. Seçenekler pgBackRest 2.60.0 belgeleriyle kontrol edilmiştir; kurulu paketin sürümünü karşılaştır.
sudo apt update
sudo apt install pgbackrest
/usr/bin/pgbackrest version
sudo -u postgres psql -X -d postgres -c "SHOW data_directory;"
Yeni depo ve günlük dizinlerini postgres kullanıcısına ver. Yapılandırma root tarafından yönetilsin, postgres grubu okuyabilsin. Aşağıdaki dosya oluşturma adımı yalnızca yeni deneme kurulumu içindir; mevcut yapılandırmayı veya dolu depoyu bununla değiştirme.
sudo install -d -o root -g postgres -m 0750 /etc/pgbackrest
sudo install -d -o postgres -g postgres -m 0750 /var/lib/pgbackrest /var/log/pgbackrest
# Fresh lab configuration only; do not overwrite an existing file.
sudo install -o root -g postgres -m 0640 /dev/null /etc/pgbackrest/pgbackrest.conf
sudoedit /etc/pgbackrest/pgbackrest.conf
Editörde /etc/pgbackrest/pgbackrest.conf dosyasına aşağıdaki INI içeriğini kaydet. REPLACE_WITH_RANDOM_SECRET yerine parola kasasında üretilmiş güçlü rastgele bir sır kullan; gerçek parolayı komut geçmişine yazma. İlk stanza oluşturulmadan önce şifreleme ayarını tamamla ve parolanın erişilebilir bir kurtarma kopyasını VPS dışında koru.
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=4
repo1-retention-diff=14
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=REPLACE_WITH_RANDOM_SECRET
compress-type=zst
start-fast=y
log-path=/var/log/pgbackrest
log-level-console=info
log-level-file=info
[main]
pg1-path=/var/lib/postgresql/17/main
repo1-retention-full=4 tam yedek sayısını, repo1-retention-diff=14 diferansiyel saklama sayısını belirler; bunlar hafta veya gün değildir. Tam yedekler diferansiyel sayımına da katılır. Bir tam yedek sona erdiğinde ona bağımlı diferansiyel ve artımlı yedekler de sona erer. start-fast=y başlangıç checkpoint’ini hızlandırır ve I/O yükünü artırabilir. Zstandard için geçerli seçenek değeri zst şeklindedir.
PostgreSQL’i WAL arşivlemeye hazırlamak
PostgreSQL yapılandırmasında wal_level=replica ve archive_mode=on kullan; çalışan farklı bir yapılandırmada mevcut ihtiyaçları da değerlendir. fsync ve full_page_writes etkin kalmalıdır. Arşiv komutu tamamlanmış WAL segmentlerini pgBackRest’e gönderir. Bu örnek için ek bir max_wal_senders ayarı gerekmez; o kaynak bütçesini varsa replikasyon kullanımına göre belirle.
# /etc/postgresql/17/main/postgresql.conf
wal_level = replica
archive_mode = on
archive_command = '/usr/bin/pgbackrest --stanza=main archive-push %p'
archive_timeout = '60s'
hot_standby = on
wal_level ve archive_mode değişiklikleri yeniden başlatma ister; reload yeterli değildir. Deneme kümesini yeniden başlat ve etkin değerleri kontrol et. Üretimde bu adım bağlantıları etkilediğinden planlı bakım gerektirir. archive_timeout aralık dolduğunda ve veritabanı etkinliği olduğunda segment değişimini teşvik eder; etkinliksiz bir sistemde her dakika yeni segment garantisi vermez.
sudo pg_ctlcluster 17 main restart
sudo -u postgres psql -X -d postgres -c "SELECT name, setting, pending_restart FROM pg_settings WHERE name IN ('wal_level','archive_mode','archive_command','archive_timeout','hot_standby');"
Stanza, tek bir veritabanının değil PostgreSQL kümesinin pgBackRest tanımıdır. Bu örnekte adı main. Stanza’yı oluştur ve arşiv yolunu etkin olarak kontrol et:
sudo -u postgres /usr/bin/pgbackrest --stanza=main stanza-create
sudo -u postgres /usr/bin/pgbackrest --stanza=main check
Birincil sunucuda check bir restore point oluşturur, WAL geçişi ister ve arşivlenmesini bekler; yalnızca envanter okuyan bir komut değildir. Başarısız olursa PostgreSQL ve pgBackRest günlüklerini, depo erişimini, parolayı, ikili dosya yolunu ve stanza adını incele. Başarılı kontrol, gelecekteki arşivlemenin sürekli çalışacağını kanıtlamaz.
İlk yedek ve eksiksiz systemd zamanlaması
İlk tam yedek kümenin dosyalarını kopyalar. Olağan diferansiyel yedek, son tam yedekten beri değişen dosyaları; artımlı yedek, önceki yedekten beri değişen dosyaları kapsar. Bunları otomatik olarak yalnızca değişen sayfaların kopyalanmasıyla eşitleme. Geri dönüşte ilgili bağımlı yedekler ve WAL gerekir.
sudo -u postgres /usr/bin/pgbackrest --stanza=main --type=full backup
sudo -u postgres /usr/bin/pgbackrest --stanza=main info
Tam yedek başarıyla bitmeli ve info çıktısında tamamlanma zamanı, etiketi ve türü görünmelidir. Bu etiketi kurtarma kaydına al. info depo envanterini gösterir; şu anda yeni WAL’ın başarıyla arşivlendiğini tek başına doğrulamaz. Başarılı yedek de uygulamanın doğrulandığı bir restore provasının yerini tutmaz.
Aşağıdaki dört dosyayı başlarında verilen ayrı yollara root olarak kaydet. Takvimler sunucunun saat dilimini kullanır: pazar 03:00 tam, pazartesi–cumartesi 03:00 diferansiyel yedek. Type=oneshot tamamlanan işin kapanmasını sağlar; RemainAfterExit=yes ekleme.
# /etc/systemd/system/pgbackrest-full.timer
[Unit]
Description=pgBackRest Full Backup Timer
[Timer]
OnCalendar=Sun *-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/pgbackrest-full.service
[Unit]
Description=pgBackRest Full Backup
[Service]
Type=oneshot
User=postgres
TimeoutStartSec=infinity
ExecStart=/usr/bin/pgbackrest --stanza=main --type=full backup
# /etc/systemd/system/pgbackrest-diff.timer
[Unit]
Description=pgBackRest Differential Backup Timer
[Timer]
OnCalendar=Mon..Sat *-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/pgbackrest-diff.service
[Unit]
Description=pgBackRest Differential Backup
[Service]
Type=oneshot
User=postgres
TimeoutStartSec=infinity
ExecStart=/usr/bin/pgbackrest --stanza=main --type=diff backup
Dosyaları kaydettikten sonra iki timer’ı da etkinleştir ve sonraki çalışma zamanlarını doğrula:
sudo systemctl daemon-reload
sudo systemctl enable --now pgbackrest-full.timer pgbackrest-diff.timer
systemctl list-timers pgbackrest-full.timer pgbackrest-diff.timer
Persistent=true kapalıyken kaçırılan bir çalışmayı açılışta tetikleyebilir; kaçırılan her yedek için ayrı iş kuyruğu oluşturmaz. İki timer birden gecikmişse işler çakışabilir; kilit veya başka nedenle başarısız olan yedeği görüp uygun zamanda yeniden çalıştıracak izleme gerekir. WAL arşivleme zamanlanmış yedeklerden bağımsızdır ve yalnızca tamamlanmış segmentler gönderilir. Ağ/depo arızası veya düşük WAL üretimi aktarımı geciktirebilir; bu akış anlık replikasyon değildir.
İzole bir sunucuda zamana göre PITR
Örneğin hatalı güncellemenin 10:00’da işlendiğini ve doğrulanmış son sağlıklı durumun 09:52 olduğunu varsayalım. Önce olay kayıtlarından hedefi, doğru zaman çizgisini ve o hedefi kapsayan yedek/WAL zincirini belirle. Aşağıdaki komutlar üretim sunucusunda değil, ayrı kurtarma VPS’inde uygulanır.
Hedef zamanı belirlemek
Saniyeleri tahmin etmek yerine işlem ve uygulama kayıtlarını kullan; hedefi tarih ve açık UTC farkıyla kaydet. Yedek hedef zamandan önce tamamlanmış olmalıdır. pgBackRest zaman hedefi için uygun yedeği otomatik seçebilir; sonucu günlüklerden doğrula. Daha yeni bir yedekten geçmişe gidilemez. Önceki PITR dalları varsa varsayılan en yeni timeline yerine olayın ait olduğu --target-timeline değerini belirlemek gerekebilir.
Kurtarma sunucusunu hazırlamak
Kurtarma VPS’ine aynı PostgreSQL ana sürümünü, gereken eklentileri ve uyumlu pgBackRest sürümünü kur. Yedek deposunu ve gerekli WAL’ı erişilebilir hale getir; yerel depo kullanıyorsan tutarlı bağımsız kopyasını bu sunucuya getir. /etc/postgresql/17/main altındaki dış yapılandırmayı ayrıca geri getir; veri dizini yedeğinde bulunduğunu varsayma. Uygulama bağlantılarını, zamanlanmış yedekleri ve dış entegrasyonları burada devre dışı bırak. Aşağıdaki adım yalnızca bu deneme sunucusundaki mevcut küme dizinini saklar; main.before-pitr önceden varsa durur.
# Run only on the isolated recovery VM, with the correct lab paths.
set -e
sudo pg_ctlcluster 17 main stop
sudo test ! -e /var/lib/postgresql/17/main.before-pitr
sudo mv -T /var/lib/postgresql/17/main /var/lib/postgresql/17/main.before-pitr
sudo install -d -o postgres -g postgres -m 0700 /var/lib/postgresql/17/main
pgBackRest restore komutu
PostgreSQL durmuşken, boş ve postgres sahipliğindeki 0700 izinli hedefe restore uygula. --target-action=pause hedefe ulaşınca inceleme için bekletir; hot_standby=on etkin olmalıdır. --archive-mode=off geri getirilen deneme kümesinin kaynak depoya yeni WAL yazmasını engeller. Aşağıdaki soruya yalnızca doğrulanmış hedef zamanı gir.
read -r -p 'Recorded recovery timestamp, including UTC offset: ' PITR_TARGET
: "${PITR_TARGET:?A verified recovery timestamp is required}"
sudo -u postgres /usr/bin/pgbackrest \
--stanza=main \
--type=time \
--target="$PITR_TARGET" \
--target-action=pause \
--archive-mode=off \
restore
Boş hedef için --delta gerekmez. Bu seçenek mevcut dosyaları karşılaştırıp değiştirebilir veya kaldırabilir; dolu bir dizine uygulanacaksa kapsamı ayrıca incelenmelidir. Restore başarılı bittikten sonra PostgreSQL’i başlat; WAL tekrar oynatma bu aşamada gerçekleşir.
sudo pg_ctlcluster 17 main start
sudo -u postgres psql -X -d postgres -c "SELECT pg_is_in_recovery(), pg_get_wal_replay_pause_state();"
PostgreSQL günlüklerinde hedefe ulaşıldığını doğrula. Sorgu, kurtarmanın sürdüğünü ve durumun paused olduğunu göstermelidir; yalnızca pause requested yeterli değildir. Beklenen satırları, kritik toplamları ve hatalı işlemin yokluğunu salt okunur sorgularla kontrol et. Hedefe ulaşılamadıysa veya WAL eksikse sunucuyu yazmaya açma; yedek, hedef ve timeline seçimini düzeltip boş bir hedefte yeniden dene.
Genel yöntemleri PostgreSQL yedekleme belgelerinde, kullanılan restore seçeneklerini pgBackRest kullanıcı rehberinde inceleyebilirsin. Prova verisi doğrulandıktan sonra istenirse SELECT pg_wal_replay_resume(); hedefteki beklemeyi bitirir ve kurtarmadan çıkar. Deneme sunucusunda arşivleme kapalı kalır; gerçek üretime geçişte uygulama yönlendirmesi, yeni timeline, arşivleme ve yeni yedek planı ayrıca hazırlanmalıdır.
Saklama süresi, sıkıştırma ve şifreleme
Saklama sayılarını takvimle birlikte değerlendir: haftalık dört tam yedek, mutlaka bir aylık eksiksiz PITR penceresi demek değildir. Başarısız işler veya eksik WAL pencereyi daraltır. Gereken en eski hedefi hangi yedeğin ve WAL’ın karşıladığını kontrol et. pgbackrest --stanza=main --dry-run expire silinecek bağımlılıkları önceden gösterir; otomatik expire da yedek sonrasında çalışabildiği için politikayı önceden gözden geçir.
compress-type=zst destekleyen bir kurulumda Zstandard kullanılabilir; sıkıştırma oranı ve CPU maliyeti veriyle ölçülmelidir. aes-256-cbc depo içeriğini şifreler, erişim kontrolünün yerini tutmaz. Stanza oluşturulmuş mevcut deponun şifreleme ayarını doğrudan değiştirerek dönüşüm yapma; ayrı depo ve doğrulanmış taşıma/kurtarma planı gerekir.
Yerel depo erişimini yalnızca gereken hesaplarla sınırla; bu örnekte dizinler postgres sahipliğinde 0750, parola içeren yapılandırma root:postgres 0640’tır. Yedek sunucusundaki kullanıcı ve izinler farklı olabilir. Kaynak sunucuyu kaybedince de kullanılabilecek bağımsız parola ve yapılandırma erişimini geri dönüş sırasında dene.
Yedek ve WAL akışını izlemek
Belirlediğin aralıklarla farklı bir sunucuda restore yap; örneğin aylık prova bir başlangıç politikası olabilir. Başlama/bitiş zamanı, kullanılan yedek etiketi, hedef, timeline, uygulama doğrulamaları ve erişilen RTO/RPO’yu kaydet. Paket veya saklama politikası değişince provayı tekrarla.
İzlemede son başarılı yedeğin yaşı, başarısız işler, depo kapasitesi ve kaynak pg_wal alanı birlikte değerlendirilmelidir. pg_stat_archiver son başarı/başarısızlık bilgisi verir; sayaçları zaman içindeki değişimleriyle yorumla. Hiç etkinlik olmayan dönemde eski bir arşiv zamanı tek başına hata değildir.
sudo -u postgres psql -X -d postgres -c "SELECT archived_count, last_archived_wal, last_archived_time, failed_count, last_failed_wal, last_failed_time FROM pg_stat_archiver;"
sudo journalctl -u pgbackrest-full.service -u pgbackrest-diff.service --since today
Bakım yükünü de ayrı izle. PostgreSQL autovacuum ve bloat yönetimi dosya büyümesini ve I/O davranışını anlamaya yardımcı olur. VACUUM her zaman dosyaları küçültmez; bakım işlemlerinin kendisi de WAL üretebilir. Yedek büyüklüğünü yalnızca autovacuum ayarıyla açıklama.
İzin, saat dilimi ve WAL birikmesi sorunları
Arşiv başarısızlıklarında komutun postgres hesabıyla erişebildiği ikili dosyayı, doğru stanza’yı, depo parolasını ve disk/ağ erişimini kontrol et. Çok yoğun yazma arşiv hacmini artırabilir; arşivleme aksarsa WAL kaynakta birikir. Disk dolması PostgreSQL’i durdurabilir, bu yüzden kapasite alarmı hata günlüklerinden ayrı olmalıdır.
archive_command PostgreSQL yapılandırma değeridir; satır sonuna SQL noktalı virgülü eklenmez. Yazım hatası, başarısız dış komut veya yanlış yol günlüklerden incelenmelidir. Arşiv komutunun değişmesi reload ile uygulanabilir; archive_mode veya wal_level değişikliği ise restart ister.
Bu rehberdeki PostgreSQL 17, recovery.signal ve kurtarma ayarlarını kullanır; eski recovery.conf örneklerini aynen taşıma. pgBackRest dosyaları oluşturur ama doğru yedek ve WAL kapsamını seçmek yönetim sorumluluğudur. Ayrıntılar sürekli arşivleme ve PITR belgelerinde açıklanır.
Uzak depo ve zamanlayıcı işletimi
SSH deposunda kaynak ve depo sunucularındaki pgBackRest sürümleri tam olarak eşleşmelidir. repo1-host tanımı yanında uzak kullanıcı, güvenilir SSH anahtarı/host key, sunucu tarafı stanza yapılandırması ve depo izinleri gerekir. S3 kullanıldığında bölge, endpoint, özel depo öneki ve erişim yetkileri birlikte ayarlanır. Dolu bir yerel deponun yolunu değiştirerek yedeklerin taşındığını varsayma; yeni hedefte stanza, tam yedek, arşiv akışı ve restore doğrulanmalıdır.
Oneshot yedek işi için StopWhenUnneeded gerekmez. TimeoutStartSec=infinity büyük yedeği keyfî bir başlangıç süresinde kesmez, ancak takılan veya beklenenden uzun süren işler için süre alarmı gerekir. Timer etkin görünmesi son yedeğin başarılı olduğu anlamına gelmez; servis çıkış durumunu ve yedek envanterini izle.
Uzak depo yalnızca başka bir konum değildir: VPS silinmesi veya kaynak hesabın ele geçirilmesi durumunda erişim ve silme yetkilerinin nasıl ayrıldığını da planla. Nesne yaşam döngüsü kuralları pgBackRest’in sakladığı yedekleri, WAL’ı veya timeline geçmişini erkenden silmemelidir. Şifreleme anahtarı kayıp bir depoyu kullanılabilir hale getirmez; hem veri hem anahtar gerekir.
Kurtarma çalışması için kayıt şablonu
Runbook’a küme sürümü/adı, veri ve tablespace yolları, dış yapılandırma konumu, depo erişim yöntemi ve anahtarın nereden alınacağını yaz. Parolanın kendisini geniş erişimli runbook’a koyma. İşlem başlamadan yedek etiketi, bitiş zamanı, hedef zaman ve timeline kaydı oluştur.
Kabul ölçütlerini somutlaştır: ilgili küme durmuş olmalı, hedef dizin boş olmalı, restore tamamlanmalı, PostgreSQL istenen hedefte beklemeli ve uygulamanın kritik veri kontrolleri geçmeli. Her başarısızlık için geri dönüş veya yeniden deneme adımını önceden belirle.
Harici tablespace kullanan bir sistemi bu örneğe doğrudan uyarlama. Dosyaların özgün mutlak yollara yazılmasını önleyecek tablespace eşlemelerini ve WAL içindeki tablespace işlemlerini incele. Aynı makinede yalnızca farklı port seçmek; socket, yapılandırma, tablespace ve dış bağlantı çakışmalarını tek başına çözmez.
Üretime geçişte son kontroller
PITR sonrası uygulama önbelleği, görev kuyruğu veya başka sistemler daha yeni olayları tutabilir. Veri geri dönüşünün bu sistemlerle tutarlılığını doğrula; tüm önbellekleri körlemesine silmek yerine uygulamanın yöntemini uygula. İşlem sırasında alınan dış ödemeler gibi etkiler PostgreSQL’i geri getirince kendiliğinden geri alınmaz.
postgresql.conf, pg_hba.conf, include dosyaları, gerekli eklentiler ve pgBackRest yapılandırması sürüme uygun olarak korunmalıdır. Dış yapılandırmanın bir kopyasını geri getirmek, eski ağ ve entegrasyon ayarlarını deneme ortamında güvenli hale getirme gereğini ortadan kaldırmaz.
Kurtarma yetkili başka bir kişinin, kaynak sunucuya erişmeden depoyu ve parolayı kullanabildiğini doğrula. Bir sonraki yedek silme veya saklama azaltma işlemini bu prova sonuçlarına göre değerlendir.
Tamamlanmış bir yedekleme akışının ölçütü
pgBackRest kurulumu; zamanında biten yedekler, izlenen WAL aktarımı ve doğrulanmış geri dönüş birlikte çalıştığında amacına ulaşır. Yerel örneğin ardından bağımsız depoda aynı hedefe ulaşılabildiğini gösteren bir prova kaydı oluştur.





