İçindekiler
- 1 Hiç “Keşke Zamanı Geri Alsam” Dediğin Oldu mu?
- 2 Neyi, Neden Yaptığımızı Bilerek Başlayalım
- 3 Ortamı Kuruyoruz: pgBackRest, PostgreSQL ve Yol Haritası
- 4 İlk Yedek: Tam, Sonra Diferansiyel; WAL’ler Aksın
- 5 PITR: Zamanı Geri Sarmak Nasıl Hissettirir?
- 6 Küçük İnce Ayarlar: Tutma Politikası, Sıkıştırma, Şifreleme
- 7 Yedekleri Düzenli Test Etmek: Runbook, Alarm, Küçük Provalar
- 8 Gerçek Hayattan Küçük Dersler: İzinler, Saat Dilimi, WAL Taşkını
- 9 Yapılandırmayı Zenginleştirmek: Uzak Repo, Ayrı Disk, Sistem Servisleri
- 10 Adım Adım Özet Akış: Kur, Doğrula, Yedekle, Test Et
- 11 Sık Karşılaştığım Sorular ve Küçük Notlar
- 12 Kapanış: Bugün Küçük Bir Adım, Yarın Büyük Bir Rahatlık
Hiç “Keşke Zamanı Geri Alsam” Dediğin Oldu mu?
Bir sabah ofiste kahvemi koydum, terminali açtım, gözüm yarı uykulu bir migration komutunu çalıştırdım. Son anda fark ettim ki, yanlış veritabanındayım. Birkaç tabloyu uçurup, yüzümde o malum donuk ifade ile kaldım. “Keşke bir iki saat öncesine dönebilsem” dedim. İşte tam burada PostgreSQL’de PITR (Point-In-Time Recovery) ve pgBackRest sahneye çıkıyor. Zamanı geri almak gibi bir sihir değil belki, ama en azından veritabanını belirli bir zamana geri döndürmek mümkün. Bu yazıda, bir VPS üzerinde sıfırdan WAL arşivleme ve pgBackRest ile yedeklemeyi kurup PITR yapmayı adım adım anlatacağım.
Hedefimiz şu: Basit ama sağlam bir kurulum, anlaşılır bir yapılandırma, düzenli yedekler ve gerektiğinde paniksiz bir geri dönüş. Komutları tek tek vereceğim, ama sakince, her adımın nedenini konuşa konuşa gideceğiz. Bir yerde tıkanırsan, merak etme; deneme yanılma ile yoğrulmuş küçük hikayeler paylaşacağım. Hani şu tahtaya tebeşirle not etmiş gibi hatırlatmalar olacak.
Okurken aklında bir senaryo canlandır: Üretim veritabanın ufak bir VPS’te koşturuyor, trafik orta halli, ama veri önemli. Bir kullanıcı hatası, beklenmeyen bir sorgu, gereksiz bir “DROP” – her şey olabilir. O yüzden basit bir rutin kuruyoruz: Tam yedekleri düzenli al, WAL’leri akıt, PITR ile geri dönmeyi prova et. Hazırsan, önce birkaç temel kavramı “mutfağa girer gibi” sakin sakin netleştirelim.
Neyi, Neden Yaptığımızı Bilerek Başlayalım
Mesela şöyle düşün: Veritabanını bir fotoğraf albümü gibi gör. Tam yedek, o albümün net bir kopyası. Ama arada çektiğin fotoğrafları tek tek albüme eklemek istersin. WAL (Write-Ahead Logging) tam bu. Veritabanında yapılan her değişiklik önce bu günlük dosyalarına yazar. Biz bu günlükleri saklarsak, tam yedekten başlayıp “zamanda ileri sararak” belirli bir saniyeye ulaşabiliriz. İşte PITR böyle çalışır.
pgBackRest ise işin aşçıbaşısı. Tam yedek alır, artımlı yedekleri yönetir, WAL arşivleme için PostgreSQL ile el sıkışır, saklama politikalarını uygular ve geri yüklerken rehberlik eder. Tek başına PostgreSQL de yedeklenir, ama pgBackRest işi düzenli ve güvenli hale getirir. Hata payını azaltır, adımları kalıba sokar.
VPS tarafında da küçük ama önemli noktalar var. Disk I/O yetenekleri, ağ gecikmesi, depolama alanı, hatta saat dilimi. Hepsi sonunda PITR deneyimini etkiler. Mesela loglara bakarken bir saat kayması, seni yanlış hedef zamana sürükleyebilir. Bu yüzden “ne, nerede, neden” sorularını baştan netleştirmek iyi bir alışkanlık.
Ortamı Kuruyoruz: pgBackRest, PostgreSQL ve Yol Haritası
Hangi parçalara ihtiyacımız var?
Senaryomuz şöyle: Ubuntu/Debian tabanlı bir VPS, PostgreSQL 14 veya 15, yanında pgBackRest. Depolamayı yerelde tutacağız; istersen sonra uzak bir sunucuya da replikasyon veya dosya senkronizasyonu ekleyebilirsin. Temel hedef, tek bir VPS’te bile düzgün yedek akışı kurmak.
pgBackRest kurulumu
Dağıtıma göre paket depolarında pgBackRest mevcut. Yoksa kaynak koddan kurulum da olur ama paketler işimizi görecektir. Örneğin Debian/Ubuntu tarafında:
sudo apt update
sudo apt install -y pgbackrest
# PostgreSQL kimdir, nerededir? Tipik dizin örnekleri:
# /var/lib/postgresql/15/main (Debian/Ubuntu)
# pgdata değişebilir, dikkat.
pgBackRest kendi yapılandırma klasörünü kullanır. Varsayılan olarak /etc/pgbackrest ve repository için /var/lib/pgbackrest iyidir. Dizin izinleri ve sahiplik çok kritik. pgBackRest’i postgres kullanıcısı çalıştırmalı. Reponun sahibi de o olmalı.
sudo mkdir -p /etc/pgbackrest
sudo mkdir -p /var/lib/pgbackrest
sudo chown -R postgres:postgres /etc/pgbackrest /var/lib/pgbackrest
sudo chmod 750 /var/lib/pgbackrest
Şimdi temel bir /etc/pgbackrest/pgbackrest.conf yazalım. Basit başlayalım; sonra zenginleştiririz.
sudo -u postgres bash -c 'cat > /etc/pgbackrest/pgbackrest.conf <<"EOF"
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=4
repo1-retention-diff=14
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=GUVENLI_BIR_SIFRE
compress-type=zst
start-fast=y
[main]
pg1-path=/var/lib/postgresql/15/main
EOF'
Burada saklama politikalarını kabaca çizdik. Tam yedeklerden dört kopya, diferansiyel yedeklerden iki haftalık bir geçmiş gibi düşünebilirsin. Parola üretmek için basit bir şifre türetme scripti kullanabilirsin. Şifreyi saklarken de gizli dosyalarda tutmayı unutma. Evde anahtarını matın altına koymazsın, burada da koyma.
PostgreSQL’i WAL arşivlemeye hazırlamak
Şimdi veritabanına dönelim. wal_level en azından “replica”, archive_mode açık olacak. archive_command ise pgBackRest’in archive-push komutunu çağıracak. postgresql.conf’u düzenleyelim.
# /etc/postgresql/15/main/postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'pgbackrest --stanza=main archive-push %p'
max_wal_senders = 3
Ardından PostgreSQL’i yeniden yükle:
sudo systemctl reload postgresql
pgBackRest’e bu kümenin bir adı olduğuna dair “stanza” tanıtacağız. Bu, birden fazla veritabanını takip etmek istediğinde hayat kurtarır. Tek veritabanımız var ama yine de iyi bir alışkanlık.
sudo -u postgres pgbackrest --stanza=main stanza-create
sudo -u postgres pgbackrest --stanza=main check
“check” çıktısında arşiv komutu, repo erişimi ve dizin izinleriyle ilgili uyarılar almamalısın. Bir uyarı gelirse genellikle sahiplik veya yol hatasıdır. Sakin ol, tekrar kontrol et.
İlk Yedek: Tam, Sonra Diferansiyel; WAL’ler Aksın
İlk tam yedeği alalım. Bu, albümün eksiksiz kopyası. Sonrasında diferansiyel ve artımlı yedeklerle yalnızca değişen sayfaları ekleriz.
sudo -u postgres pgbackrest --stanza=main --type=full backup
sudo -u postgres pgbackrest info
“info” çıktısı çok şeyi söyler: kaç yedeğin var, hangi tarihte alınmış, toplam boyutlar, WAL arşivleme durumu. Bu komutla düzenli olarak yoklama yapmak, “her şey yolunda mı?” sorusuna çabuk cevap verir.
Yedekleri rutin hale getirmek için bir zamanlayıcı ekle. Cron olabilir, ama ben systemd timer kullanmayı seviyorum. Hem loglar düzenli, hem de servis mantığına oturuyor.
# /etc/systemd/system/pgbackrest-full.timer
[Unit]
Description=pgBackRest Full Backup Timer
[Timer]
OnCalendar=Sun 03:00
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/pgbackrest-full.service
[Unit]
Description=pgBackRest Full Backup
[Service]
Type=oneshot
User=postgres
ExecStart=/usr/bin/pgbackrest --stanza=main --type=full backup
# Diferansiyel için benzer bir çift ekleyebilirsin:
# /etc/systemd/system/pgbackrest-diff.timer (OnCalendar=Mon..Sat 03:00)
# /etc/systemd/system/pgbackrest-diff.service (ExecStart=... --type=diff)
Timer’ları etkinleştir:
sudo systemctl daemon-reload
sudo systemctl enable --now pgbackrest-full.timer
# Diff için de benzer şekilde enable/now
Artık resim netleşiyor: Pazar sabahları tam yedek, hafta içi diferansiyeller. WAL arşivleme ise sürekli akıyor. Yani veritabanındaki değişiklikler “anbean” repo’ya taşınıyor. Bu akış, PITR’nin yakıtı.
PITR: Zamanı Geri Sarmak Nasıl Hissettirir?
Gelelim işin en tatlı kısmına. Diyelim ki saat 10:00’da yanlış bir güncelleme çalıştırdın, orada dengesiz bir veri oluştu. Sen aslında 09:52’ye geri dönmek istiyorsun. O halde önce bir nefes al, sonra şu adımları takip et.
Hedef zamanı belirlemek
Uygulama loglarından, PostgreSQL loglarından veya olay hatırandan hedef zamanı netleştir. Saniye seviyesinde kabaca bir hedef seç. “Biraz öncesi de olur” dersen, birkaç saniye önceyi kullan. Timezone’u unutma; sunucu UTC ise, yerel saatine göre çevirmelisin.
Veritabanını durdurmak
Restorasyon öncesi PostgreSQL’i kapatırız. Veri dizinini boşaltmak veya kenara almak gerekir. pgBackRest, restore sırasında dizini doldurur.
sudo systemctl stop postgresql
sudo mv /var/lib/postgresql/15/main /var/lib/postgresql/15/main.bak.$(date +%s)
sudo -u postgres mkdir -p /var/lib/postgresql/15/main
pgBackRest restore komutu
Artık geri yüklemeyi, hedef zamana göre tetikliyoruz. pgBackRest, PostgreSQL 12+ sürümlerinde gereken recovery.signal ve restore ayarlarını otomatik yazar. Hedef zamanı ve davranışı net söylersin, o da gereken WAL’leri sırayla uygular.
sudo -u postgres pgbackrest
--stanza=main
--type=time
--target='2025-11-11 09:52:00'
--target-action=promote
--delta
restore
Burada “delta”, var olan dosyaları tekrar indirmemek için akıllı bir kısayol. Ama ilk denemelerde temiz dizinle çalışmak daha anlaşılır olabilir. Restore bitince PostgreSQL’i başlat:
sudo systemctl start postgresql
Logları kontrol et. Genelde “recovery” tamamlandı, “promote” edildi gibi net mesajlar görürsün. Hedef saniyeye gelince sistem ayağa kalkar. Şimdi kritik an: Uygulamada kısa bir sağlık kontrolü yap. O yanlış güncellemenin etkileri kaybolmuş mu, beklediğin veri görünür mü?
Burada bir parantez: Daha kapsamlı akış ve sinyal dosyaları için PostgreSQL yedekleme ve kurtarma akışını incelemek iyi gelir. Ayrıca pgBackRest’in ayrıntılı seçenekleri de çok zengin; merak ettikçe pgBackRest kullanıcı rehberini elinin altında tut.
Küçük İnce Ayarlar: Tutma Politikası, Sıkıştırma, Şifreleme
Yedeklemek kadar silmek de sorumluluk ister. Depolama alanı sınırlıysa, retention değerlerini gerçekçi belirle. Tam yedek sayısı az olursa geri dönüş yolların daralır; çok olursa disk dolar. İyi bir başlangıç, aylık dört tam yedek ve aralarda iki haftalık diferansiyeller. Bu, hem alanı hem de geri dönüş esnekliğini dengeler.
Sıkıştırmada zstd gayet seri ve verimli. CPU bütçeni zorlamadan sağlam kazanç sağlar. Şifreleme için AES-256 iyi bir tercih. Ama anahtar yönetimini ciddiye al. Yedek anahtarını farklı bir yerde, ayrı bir kasada tutmak gibi düşün. Asıl sunucuda tuttuğun şifre, başka bir yedekleme notunda tekrar edilmeli ama herkese açık olmamalı.
İşin bir de repo güvenliği kısmı var. O dizine herkesin yazabilmesi olmaz. Sahiplik postgres, mod 750 veya 700 olsun. Yedeklerin bütünlüğünü bozacak en küçük izinsiz değişiklikte restorasyon süreci maskara olur. O yüzden izinler konusuna “kırılacak eşya” hassasiyetiyle yaklaş.
Yedekleri Düzenli Test Etmek: Runbook, Alarm, Küçük Provalar
Bir gün gerçekten PITR yapmak zorunda kalırsan, o an “ilk kez” yapmak istemezsin. Bu yüzden küçük bir test planı şart. Ben genelde şöyle yaparım: Ayda bir staging bir VPS’te orijinal sunucunun yedeğini indirir, restore dener, uygulamayı smoketest ile yoklarım. Rutin olunca, üretimde hata olduğunda elin hiç titremez.
pgBackRest’in bilgi komutları günlük hayatta çok pratik. “info” ile durum al, “check” ile tutarlılık yokla. WAL arşivlemenin aktığını teyit etmek için arşiv klasöründen dosya akışına ara ara bak. PostgreSQL tarafında “archive” ile ilgili log satırları temiz mi, tekrar eden hata var mı?
sudo -u postgres pgbackrest info
sudo -u postgres pgbackrest --stanza=main check
Yine benzer bir konuda veritabanı sağlığını uzun vadede korumak için Autovacuum ayarlarını tatlı tatlı düzenlemek ve bloat’la barışmak da iyi bir alışkanlık. Yedekleme ne kadar mükemmel olursa olsun, şişmiş tablolar ya da ihmal edilmiş vakum işleri restorasyonu da ağırlaştırır.
Gerçek Hayattan Küçük Dersler: İzinler, Saat Dilimi, WAL Taşkını
İşin mutfağında sık takılan birkaç taş var. Birincisi izinler. pgBackRest repo’su ve /etc/pgbackrest altında yanlış sahiplik veya fazla açık izinler olursa, bazen kibar uyarılar, bazen de sert hatalar alırsın. İkincisi saat dilimi. PITR hedefini yazarken UTC mi, yerel saat mi, net ol. Üçüncüsü WAL taşkını. Anlık çok yoğun yazma olduğunda repo’ya akan WAL sayısı artar. Bu normaldir; disk alanını ve ağını buna göre planla.
Bir kere de şunu yaşamıştım: “archive_command” güzelce yazılmış ama sonuna noktalı virgül koymayı unutmuşum. postgresql.conf’da basit bir yazım hatası bile arşivlemeyi sessizce bozabilir. Bir reload sonrası logları göz ucuyla kontrol etmek bu yüzden kritik.
Bir de sürüm ayrıntısı var: PostgreSQL 12’den itibaren recovery.conf kalktı, recovery.signal ve standby.signal gibi sinyal dosyaları geldi. pgBackRest bu ayrıntıları senin yerine hallediyor ama aklında bulunsun. Merak edersen sürekli arşivleme ve PITR rehberine göz atabilirsin.
Yapılandırmayı Zenginleştirmek: Uzak Repo, Ayrı Disk, Sistem Servisleri
İşler ciddileşince yedekleri uzak bir sunucuya aktarmak istersin. pgBackRest bu konuda esnek; SSH üzerinden repo-host tanımıyla uzak depoyu yönetebilirsin. Ağ gecikmesi artar ama felaket senaryosunda veriyi başka bir yerde tutmanın güveni paha biçilmez. Yerel disk de ayrıca önemli; aynı VPS’te bile olsa yedekleri ayrı bir diske koymak riski azaltır.
Systemd tarafında küçük incelikler var. Servislere “StopWhenUnneeded” gibi parametrelerle kısa ömürlü işler tanımlarsın. Timer’lar başarısız olursa journalctl ile çıktıyı al, hatayı birlikte çözen arkadaşlar gibi sevgiyle yaklaşırsın. Kurtarma anında bir runbook elinin altında olsun: “Önce durdur, yedek dizini taşır, restore, başlat, kontrol listesi.” Tek sayfalık bir not bile zor anlarda altın değerinde.
Bu aşamada “izleme”yi de düşün. Yedek boyutları, son yedek zamanı, WAL akışı, başarısız yedek denemeleri. Ufak bir panel, bir iki alarm kuralı ekleyince geceleri daha rahat uyursun. pgBackRest, komutlarla okunabilir bir özet verdiği için basit bash script’leriyle bile uyarılar kurulur.
Adım Adım Özet Akış: Kur, Doğrula, Yedekle, Test Et
Şimdiye kadar anlattıklarımızı küçük bir akış halinde kafanda netleştir: Önce pgBackRest’i kurdun ve repo ile konfigürasyonu hazırladın. PostgreSQL tarafında archive_mode’u açtın, archive_command’ı pgBackRest’e bağladın. Stanza’yı yarattın, check ile doğruladın. İlk tam yedeği aldın. Timer’larla düzen kurdun. Sonra bir gün, bir şeyler ters gitti. Panik yok. PostgreSQL’i durdurdun, data dizinini kenara aldın, restore’u hedef zamana göre çalıştırdın, servis başladı ve gülerek çayını yudumladın.
Uzun gibi görünse de birkaç kez yaptıktan sonra elin alışıyor. Hele bir iki test restore yaptıysan, gerçek bir geri dönüş anında elin kaymıyor. Şu da gerçek: Yedek almak, sadece komut çalıştırmak değil. Test etmek, saklama politikasını doğru ayarlamak, izlemek ve belgelemek de bu işin bir parçası.
Buraya kadar teknik anlatımda ayrıntıya girdik ama hiçbiri gözünü korkutmasın. Adımların her biri anlamlı ve sonucunu anında görüyorsun. Birkaç küçük prova ile senin için sıradan bir rutine dönüşecek.
Sık Karşılaştığım Sorular ve Küçük Notlar
“Peki, tamam da en sık neler ters gidiyor?” dersen, aklıma ilk gelenler: wrong owner/permissions, archive_command yazım hataları, yetersiz disk, hedef zamanın yanlış time zone ile hesaplanması, repo şifresinin unutulması. Bunların hepsi, küçük bir kontrol listesiyle önlenebilir. Hatta restorasyon sonrası uygulama cache’lerini temizlemeyi bile not düşmek iyi fikir. Geri dönüş tamamlanıyor ama uygulama katmanı eski cache’i gösterince “hata var” sanıyorlar. Sorun bir değil, iki katmanda olabiliyor.
Konfigürasyon dosyalarını değiştirirken kopyasını al. Özellikle postgresql.conf ve pgbackrest.conf. Bir şeyleri bozarsan geri dönüş çok rahatlar. Küçük dokunuşlar, büyük rahatlamalar.
Ve son bir parola notu: repo şifresini yalnızca konfigürasyonda bırakma. Güvenli bir parola kasasında, başka bir yerde, hatta yazdırılmış ama kilitli bir çekmecede bile tutabilirsin. En kötü gün geldiğinde tek bir düğüme bağlı kalmak istemezsin.
Kapanış: Bugün Küçük Bir Adım, Yarın Büyük Bir Rahatlık
Bazen birkaç komut, birkaç iyi alışkanlık ve bir tutam sabır, işini bambaşka bir seviyeye taşır. pgBackRest ile WAL arşivleme ve PITR tam da böyle. İlk bakışta karmaşık görünebilir ama bir kere adımları izleyince gerisi çorap söküğü gibi geliyor. Üstelik bu yaklaşım, sadece veri kurtarmak için değil, gönül rahatlığıyla uyumak için de güzel bir yatırım.
Sana son birkaç pratik tavsiye bırakayım: Önce küçük bir veritabanında deneme yap. Bir tablo oluştur, birkaç satır ekle, yanlış bir güncelleme yap ve PITR ile geri dön. Sonra bunu yaz; bir “runbook” olarak ekip arkadaşlarınla paylaş. Zamanlayıcıları ekle, loglara şöyle bir göz atmayı alışkanlık haline getir. İki ayda bir de tam restorasyon provası yap ki, reflekslerin diri kalsın.
İstersen tüm detayları daha da derinleştirmek için pgBackRest’in kullanıcı rehberine göz atabilir, PostgreSQL’in sürekli arşivleme ve PITR konularını sindire sindire okuyabilirsin. Umarım bu yazı sana yol gösterir. Takıldığın bir adım olursa, en kötü ihtimalle bir mola verip geri dön; bazen çözüm o arada kendini gösteriyor. Bir dahaki yazıda görüşmek üzere; verilerini sev, yedeklerini daha çok sev.
