Categories
Database Backup

**

Veri Tabanı Yöneticileri (DBA’lar) ve üretim ortamında PostgreSQL yöneten DevOps mühendisleri için, sıfıra yakın bir Kurtarma Noktası Hedefine (RPO) ulaşmak temel bir zorunluluktur. PostgreSQL’in felaket kurtarma ve Belirli Bir Zamana Geri Dönüş (PITR) yeteneklerinin merkezinde, Yazma Öncesi Günlükleme (WAL) yer alır. WAL, işlemler veritabanı dosyalarına yazılmadan önce günlüğe kaydedilerek ACID uyumluluğunu sağlarken, WAL arşivleme, bu günlükleri uzun vadeli yedekleme ve replikasyon için koruyan mekanizmadır.

Ancak, WAL arşivlemeyi yapılandırmak “ayarla ve unut” türünden bir işlem değildir. Hatalı yapılandırmalar, sessiz başarısızlıklar ve mimari yanlış anlamalar; felaket niteliğinde veri kaybına, “split-brain” (beyin bölünmesi) senaryolarına veya veritabanının tamamen devre dışı kalmasına yol açabilir.

Bu kapsamlı rehberde, PostgreSQL WAL arşivleme mimarisini inceleyecek, veri kaybına yol açan en yaygın tuzakları tanımlayacak ve veritabanınızın dayanıklı kalmasını sağlamak için üretim düzeyindeki en iyi uygulamaları özetleyeceğiz.

PostgreSQL WAL Mimarisi Hakkında Bilgi Edinme

Tuzaklara dalmadan önce, PostgreSQL’in işlem günlüklerini nasıl yönettiğini anlamak kritiktir.

PostgreSQL, tüm değişiklikleri pg_wal dizininde (10’dan önceki sürümlerde pg_xlog) bulunan WAL segmentlerine (varsayılan olarak 16MB dosyalar) yazar. Her işlem, Günlük Sıra Numarası (LSN) ile işaretlenerek sırayla kaydedilir.

Bir WAL segmenti dolduğunda, PostgreSQL yeni bir segmente geçer. pg_wal dizininin sonsuza kadar büyümesini önlemek için, PostgreSQL artık kilitlenme kurtarma veya replikasyon için gerek duyulmayan eski WAL segmentlerini geri dönüştürür veya siler.

WAL Arşivleme, bu geri dönüşüm sürecine müdahale eder. archive_mode etkinleştirildiğinde, PostgreSQL, tamamlanmış WAL segmentini silinmeden veya üzerine yazılmadan önce güvenli, ikincil bir konuma kopyalamak için kullanıcı tanımlı bir archive_command (veya PostgreSQL 15+ sürümlerinde bir archive_library) çalıştırır.

Belirli Bir Zamana Geri Dönüş (PITR) gerçekleştirmek için iki bileşene ihtiyacınız vardır:
1. Geçerli bir temel yedek (base backup).
2. Temel yedekleme zamanından hedef kurtarma zamanınıza kadar kesintisiz bir arşivlenmiş WAL dosyaları zinciri.

Eğer bu WAL zinciri koparsa, PITR işleminiz başarısız olur.

Üretim İçin WAL Arşivlemeyi Yapılandırma

WAL arşivlemeyi etkinleştirmek için postgresql.conf dosyanızı değiştirmeniz gerekir. Temel bir yapılandırma; wal_level ayarını yapmayı, archive_mode özelliğini etkinleştirmeyi ve archive_command komutunu tanımlamayı gerektirir.

# postgresql.conf
wal_level = replica             # Arşivleme için 'replica' veya 'logical' gereklidir
archive_mode = on               # Arşivleyici sürecini etkinleştirir
archive_command = 'test ! -f /mnt/nfs/archive/%f && cp %p /mnt/nfs/archive/%f'
archive_timeout = 600           # Her 10 dakikada bir WAL geçişini zorla

archive_command içinde:
* %p, arşivlenecek WAL dosyasının tam yolunu temsil eder.
* %f, WAL dosyasının dosya adını temsil eder.

Yukarıdaki yapılandırma basit görünse de, kurumsal ortamlarda basit kabuk komutlarına güvenmek önemli riskler doğurur.

WAL Arşivlemedeki Yaygın Tuzaklar

Tuzak 1: archive_command‘ın “Sessiz Başarısı”

PostgreSQL tamamen archive_command‘ın çıkış koduna güvenir. Komut 0 değerini döndürürse, PostgreSQL WAL dosyasının güvenli bir şekilde arşivlendiğini varsayar ve orijinal dosyayı geri dönüştürmeye devam eder.

Yaygın bir hata, veriler kalıcı depolamaya güvenli bir şekilde aktarılmasa bile 0 döndüren bir komut kullanmaktır. Örneğin, basit bir cp komutu, veriler hedef sunucudaki işletim sistemi sayfa önbelleğine (page cache) ulaşır ulaşmaz başarı döndürebilir. Eğer hedef sunucu, önbellek diske yazılmadan önce güç kaybederse, WAL dosyası kaybolur ancak PostgreSQL yerel kopyasını çoktan silmiş olur.

Risk: Kopuk bir WAL zinciri ve yalnızca felaket kurtarma senaryosu sırasında keşfedilen PITR gerçekleştirme imkansızlığı.

Çözüm: Arşivleme betiğinizin eşzamanlı yazmaları zorunlu kıldığından emin olun. Standart kabuk komutları kullanıyorsanız, verilerin diske yazıldığını garanti eden araçlar kullanın veya aktarım sonrası dosya boyutunu ve sağlama toplamını (checksum) doğrulayan bir sarmalayıcı betik yazın.

Tuzak 2: pg_wal Bölümünün Tükenmesi (WAL Şişmesi)

Eğer archive_command başarısız olursa (sıfır olmayan bir çıkış kodu döndürürse)—ağ kesintileri, yanlış izinler veya dolu bir hedef disk nedeniyle—PostgreSQL, WAL dosyasını pg_wal dizininde tutar ve komutu süresiz olarak yeniden dener.

Bu durum, arşivlenmemiş WAL’ları silmeyerek veri kaybını önlese de, ciddi bir erişilebilirlik riski doğurur. Eğer pg_wal dizini %100 dolan bir disk bölümünde bulunuyorsa, PostgreSQL bir PANIC hatası verir ve çöker. Veritabanı, alan açılana kadar tekrar başlamayacaktır.

Risk: Dolu bir pg_wal bölümü nedeniyle veritabanının tamamen devre dışı kalması.

Çözüm:
1. pg_wal dizinini her zaman özel bir disk bölümüne yerleştirin.
2. pg_wal dizininin boyutu üzerinde agresif izleme uygulayın.
3. Başarısız olan arşiv komutlarını anında tespit etmek için pg_stat_archiver görünümünü izleyin.

Tuzak 3: Eksik Temel Yedekler

Bir temel yedek, yedekleme işlemi sırasında oluşturulan WAL dosyaları olmadan işe yaramaz. Dosya sistemi düzeyinde bir anlık görüntü (snapshot) alırsanız veya WAL’ları akışa almadan (-X stream kullanmadan) pg_basebackup kullanırsanız, yedeklemenin başlangıcı ve bitişi arasında oluşturulan WAL dosyalarının başarıyla arşivlendiğinden emin olmalısınız.

Eğer arşivleyiciniz yavaşsa veya başarısız oluyorsa ve bu belirli WAL dosyaları kaybolursa, temel yedek tutarlı bir duruma getirilemez.

Risk: Bozuk veya kurtarılamaz temel yedekler.

Çözüm: Gerekli WAL dosyalarını yedekleme yükünün içine dahil etmek için pg_basebackup -X stream kullanın veya temel yedekler ile WAL segmentleri arasındaki bağımlılığı otomatik olarak yöneten kurumsal yedekleme çözümlerinden yararlanın.

Tuzak 4: Zaman Çizelgesi Karmaşası ve Split-Brain Senaryoları

Bir yedek sunucu (standby) birincil (primary) sunucuya yükseltildiğinde, PostgreSQL “Zaman Çizelgesi Kimliğini” (WAL dosya adının ilk kısmı, örn. 0000000200000001000000A4) artırır. Bu, yeni birincil sunucunun eski birincil sunucunun WAL geçmişinin üzerine yazmasını engeller.

Ancak, eski birincil sunucu düzgün bir şekilde çitlenmeden (fencing) yanlışlıkla başlatılırsa (split-brain senaryosu), eski zaman çizelgesini kullanarak aynı arşiv konumuna WAL dosyaları göndermeye çalışabilir. Eğer archive_command komutunuz dosyaların üzerine körü körüne yazıyorsa, arşiv deponuzu bozabilirsiniz.

Risk: Üzerine yazılmış WAL dosyaları, bozuk arşivler ve kurtarılamaz veritabanları.

Çözüm: archive_command komutunuz mevcut bir dosyanın üzerine asla yazmamalıdır. Daha önceki temel yapılandırmada, dosyanın zaten mevcut olması durumunda açıkça hata vermesi için test ! -f /mnt/nfs/archive/%f kullandığımıza dikkat edin.

Veri Kaybı Risklerini Azaltma: Üretim İçin En İyi Uygulamalar

PostgreSQL arşivleme stratejinizi güçlendirmek için aşağıdaki en iyi uygulamaları hayata geçirin.

1. Arşivleyici Sürecini Yerel Olarak İzleyin

PostgreSQL, arşivleme sürecinizin başarısını ve başarısızlığını takip eden yerleşik bir görünüm olan pg_stat_archiver‘ı sağlar. Bu görünümü gözlemlenebilirlik yığınınızla (örneğin, Prometheus, Datadog veya Zabbix) entegre etmelisiniz.

SELECT 
    archived_count,
    last_archived_wal,
    last_archived_time,
    failed_count,
    last_failed_wal,
    last_failed_time,
    stats_reset
FROM pg_stat_archiver;

Yapılandırılacak uyarı eşikleri:
* failed_count artarsa uyarı verin.
* now() ile last_archived_time arasındaki zaman farkı RPO eşiğinizi (örneğin 15 dakika) aşarsa uyarı verin; düşük trafikli veritabanlarında archive_timeout ayarlanmadığı sürece doğal gecikmeler olabileceğini unutmayın.

2. archive_timeout‘tan Yararlanın

Düşük yazma hacmine sahip veritabanlarında, 16MB’lık bir WAL dosyasının dolması saatler sürebilir. Dolana kadar arşivlenmez. Sunucu çökerse ve yerel disk kaybolursa, saatlerce süren işlemleri kaybedersiniz.

archive_timeout = 600 (10 dakika) ayarını yapmak, PostgreSQL’i dolu olmasa bile yeni bir WAL dosyasına geçmeye ve mevcut olanı arşivlemeye zorlar. Bu, kısmen dolu WAL dosyaları nedeniyle biraz daha yüksek depolama kullanımı pahasına, RPO’nuzun 10 dakikayı aşmamasını garanti eder.

3. archive_library‘ye Geçiş (PostgreSQL 15+)

Tarihsel olarak, archive_command her bir WAL dosyası için yeni bir kabuk süreci başlatırdı. Dakikada yüzlerce WAL dosyası üreten yüksek trafikli ortamlarda, kabuk süreçlerini çatallamanın (forking) yükü bir performans darboğazı haline gelir.

PostgreSQL 15, archive_library parametresini getirerek WAL arşivlemenin dinamik olarak yüklenen C modülleri tarafından yönetilmesine olanak tanıdı. Bu, kabuk çatallama yükünü ortadan kaldırır ve çok daha sağlam, yüksek performanslı bir arşivleme mekanizması sağlar. PostgreSQL 15 veya daha yüksek bir sürümdeyseniz, özel arşiv modüllerini destekleyen yedekleme araçlarını arayın.

4. Belirli Bir Zamana Geri Dönüşü (PITR) Düzenli Olarak Test Edin

Test edilmemiş bir yedek, yedek değildir; bir temennidir. WAL arşivlemenizin doğru çalıştığını, WAL zincirinizin kopmadığını ve temel yedeklerinizin tutarlı olduğunu doğrulamanın tek yolu, rutin ve otomatik PITR testleri yapmaktır.

Geçici bir örnek oluşturun, temel yedeği geri yükleyin, arşivinizden çekmek için restore_command‘ı yapılandırın ve belirli bir zaman damgasına kurtarma yapın. Veritabanının tutarlı bir duruma ulaştığını ve bağlantılara açıldığını doğrulayın.

CloudSave ile Kurumsal Yedekleme ve Kurtarma

archive_command için özel kabuk betiklerini yönetmek, WAL tekilleştirmeyi (deduplication) ele almak ve işlem günlükleri için güvenli, tesis dışı depolama sağlamak, BT ekipleri için hızla operasyonel bir yük haline gelebilir.

CloudSave, kurumsal PostgreSQL ortamları için tam da bu noktada önemli bir değer sağlar. CloudSave, yukarıda tartışılan manuel tuzakları ortadan kaldırmak için PostgreSQL’in yerel yedekleme ve WAL arşivleme API’leri ile doğrudan entegre olur.

Kırılgan bash betikleri yazmak yerine, CloudSave aşağıdakileri sağlayan sağlam, aracı tabanlı veya aracısız bir entegrasyon sunar:
* Teslimat Garantisi: Standart kabuk komutlarını, güvenli tesis dışı veya bulut depolamaya yapılan doğrulanmış, sağlama toplamı onaylı aktarımlarla değiştirir.
* WAL Şişmesini Önler: pg_wal dizinini aktif olarak izler ve bölüm tükenmesi gerçekleşmeden çok önce yöneticileri uyarır.
* PITR’yi Otomatikleştirir: Sezgisel bir arayüz aracılığıyla Belirli Bir Zamana Geri Dönüşü basitleştirir. Kurtarmak istediğiniz tam dakikayı seçersiniz ve CloudSave, doğru temel yedeği otomatik olarak alır ve bu duruma ulaşmak için gereken tam WAL dosyası dizisini akışa alır.
* Zaman Çizelgelerini Yönetir: PostgreSQL zaman çizelgesi geçmişlerini akıllıca yöneterek, yük devretme (failover) ve split-brain senaryolarının yedekleme deponuzu bozmamasını sağlar.

WAL yönetiminin ağır iş yükünü CloudSave’e devrederek, DBA’lar RPO ve RTO SLA’larının kurumsal düzeyde bir platform tarafından korunduğunu bilerek sorgu optimizasyonuna ve veritabanı performansına odaklanabilirler.

Sonuç

PostgreSQL WAL arşivleme, veritabanı felaket kurtarmanın omurgasıdır. Bir dosyayı bir dizinden diğerine kopyalama kavramı basit görünse de, uç durumlar—sessiz başarısızlıklar, disk tükenmesi ve zaman çizelgesi sapmaları—veri bütünlüğü için ciddi riskler oluşturur.

pg_wal mimarisini anlayarak, yıkıcı archive_command yapılandırmalarından kesinlikle kaçınarak, pg_stat_archiver‘ı izleyerek ve CloudSave gibi kurumsal yedekleme platformlarından yararlanarak, donanım arızalarına, insan hatalarına ve felaket niteliğindeki kesintilere, tek bir onaylanmış işlemi bile kaybetmeden dayanabilen dirençli bir PostgreSQL altyapısı oluşturabilirsiniz.

Veri kaybına yol açan yaygın PostgreSQL WAL arşivleme tuzaklarını keşfedin. Uzman DBA en iyi uygulamalarını, yapılandırma ipuçlarını ve kurumsal veritabanları için güvenilir Belirli Bir Zamana Geri Dönüş (PITR) sağlamanın yollarını öğrenin.