Write-Ahead Logging (WAL), PostgreSQL'in dayanıklılık (durability) ve kurtarılabilirlik (recoverability) sağlamak için kullandığı temel bir mekanizmadır. Bu yaklaşım, veri dosyalarına yapılan tüm değişikliklerin, önce kalıcı depolama birimine kaydedilen bir log kaydı olarak yazılması prensibine dayanır. Bu metodoloji, ACID (Atomicity, Consistency, Isolation, Durability) özelliklerinden özellikle Dayanıklılık (Durability) ve Atomiklik (Atomicity) garantilerini sağlamanın merkezinde yer alır. Bir işlem commit edildiğinde, WAL kayıtlarının diske yazıldığından emin olunması, sistem çökmelernden sonra bile veri kaybını önler.
WAL segment dosyaları, tipik olarak 16 MB boyutunda olup, `pg_wal` dizini altında saklanır. Her segment, bir dizi Log Sequence Number (LSN) ile etiketlenmiş kayıt içerir. LSN, WAL veri akışındaki her bir baytın benzersiz konumunu gösteren ve sistemin kurtarma sırasında nereden başlayıp nerede duracağını belirleyen kritik bir göstergedir. Bu sayede, PostgreSQL veritabanı kümesi (cluster), fiziksel bir yedekten (base backup) ve ardından gelen WAL segmentlerinin uygulanmasıyla (replay) herhangi bir noktaya geri yüklenebilir.
Checkpoint işlemi, WAL mimarisinin verimliliği ve kurtarma süresi açısından hayati bir rol oynar. Bir checkpoint sırasında, tüm kirli (dirty) bellek sayfaları (buffer pages) veri dosyalarına yazılır ve checkpoint tamamlandığında, bu noktaya kadar olan WAL kayıtları artık güvenli bir şekilde arşivlenebilir veya silinebilir hale gelir. Checkpoint frekansı, `checkpoint_timeout` ve `max_wal_size` parametreleri ile yönetilerek performans ve kurtarma süresi arasında denge kurulur.
| Kavram | Açıklama | İlgili PostgreSQL Parametresi |
|---|---|---|
| LSN (Log Sequence Number) | WAL akışındaki bayt konumunu gösteren benzersiz tanımlayıcı. | N/A (Sistem tarafından yönetilir) |
| Checkpoint | Bellekten diske veri senkronizasyonu yapılan ve kurtarma başlangıç noktası oluşturan süreç. | checkpoint_timeout, max_wal_size |
| WAL Segment | WAL kayıtlarının saklandığı 16 MB'lık dosya birimi. | wal_segment_size |
| Commit Log (CLOG) | İşlemlerin commit durumunu takip eden, WAL ile yakından entegre meta-veri. | N/A |
Bu temel bileşenlerin anlaşılması, WAL arşivlemenin neden sadece bir yedekleme değil, aynı zamanda sürekli veri koruma stratejisinin ayrılmaz bir parçası olduğunu kavramak için gereklidir. Arşivleme mekanizması, checkpoint ile işaretlenmiş bu güvenli noktalardan sonraki WAL segmentlerinin yönetiminden sorumludur.
Archiving Mekanizmasının Çalışma Prensipleri
PostgreSQL'de WAL arşivleme, birincil işlem olan WAL yazımından ayrı ve asenkron çalışan bir arka plan sürecidir. Temel amaç, bir checkpoint'ten sonra artık `pg_wal` dizininde tutulması gerekli olmayan (çünkü değişiklikler zaten veri dosyalarına yazılmıştır) WAL segmentlerini, kalıcı ve güvenli bir uzak konuma kopyalamaktır. Bu süreç, `archive_mode = on` yapılandırması ile aktif edilir. Aktif edildiğinde, PostgreSQL her bir WAL segmentini doldurup kapattığında, önceden tanımlanmış bir komutu (`archive_command`) çalıştırarak bu segmenti arşivlemeye teşvik eder.
`archive_command` parametresi, genellikle bir kabuk komutunu belirtir ve `%p` (kaynak WAL dosya yolu) ile `%f` (sadece WAL dosya adı) yer tutucularını kullanır. Bu komutun başarılı bir şekilde (0 çıkış kodu ile) tamamlanması, PostgreSQL'e ilgili segmentin güvenli bir şekilde arşivlendiğini bildirir. Başarısız olması durumunda sistem, segmenti arşivleyene kadar sürekli olarak komutu tekrarlar. Bu noktada, WAL segmentlerinin arşivlenmeden önce silinmesi engellenmiş olur, bu da veri kaybı riskini ortadan kaldırır. Ancak, `pg_wal` dizini dolabilir ve bu da veritabanı işlemlerini duraklatabilir.
Arşivleme hattının güvenilirliği, `archive_command`'ın doğru yapılandırılmasına bağlıdır. Örneğin, `scp`, `rsync` veya bulut depolama CLI araçları (`aws s3 cp`, `gcloud storage cp`) yaygın olarak kullanılır. Kritik bir best practice, komutun idempotent (aynı etkiyi tekrarlayan) olmasını sağlamaktır; yani aynı dosyayı birden fazla kez kopyalamaya çalışmanın bir hataya yol açmaması veya veri bütünlüğünü bozmaması gerekir.
- 1. Tetikleyici: Bir WAL segmenti dolduğunda ve bir sonrakine geçiş yapıldığında veya bir manuel `pg_switch_wal()` çağrısı yapıldığında arşivleme komutu tetiklenir.
- 2. Komut Yürütme: PostgreSQL, tanımlı `archive_command`'ı, kaynak dosya yolu (`%p`) ve hedef dosya adı (`%f`) argümanları ile çalıştırır.
- 3. Başarı Onayı: Komut başarıyla (çıkış kodu 0) tamamlanırsa, PostgreSQL bu segmentin arşivlendiğini kaydeder ve gerektiğinde silinebilir.
- 4. Sürekli Deneme: Komut başarısız olursa (çıkış kodu != 0), PostgreSQL periyodik olarak (her 60 saniyede) komutu yeniden dener.
Arşivleme gecikmesi (archive lag), üretim ortamlarında izlenmesi gereken önemli bir metrikdir. Bu gecikme, henüz arşivlenmemiş WAL segmentlerinin boyutu ve sayısı olarak ölçülür. Yüksek gecikme, bir felaket durumunda daha fazla veri kaybı riski (RPO - Recovery Point Objective) anlamına gelir. `pg_stat_archiver` sistem görünümü, arşivleme istatistiklerini, son başarılı ve başarısız arşivleme zamanlarını ve gecikmeye dair değerli bilgileri sağlar.
| Parametre | Varsayılan Değer | Açıklama ve Etkisi |
|---|---|---|
archive_mode |
off | on, off, ya da always değerlerini alır. "always" genellikle standby sunucularda kullanılır. Temel etkinleştirme parametresidir. |
archive_command |
(boş string) | WAL segmentini arşivlemek için çalıştırılacak komut. %p ve %f yer tutucularını içermelidir. Başarısızlık arşivleme birikimine neden olur. |
archive_timeout |
0 | Saniye cinsinden. Mevcut WAL segmentini, dolmasını beklemeden belirtilen süre sonunda arşivlemeye zorlar. RPO'yu sınırlamak için kullanılabilir, ancak daha fazla segment oluşturur. |
wal_keep_size |
0 | `pg_wal` dizininde, replication için bile olsa, tutulacak minimum WAL boyutu. Arşivleme gecikmesi yüksek olsa bile silinmeyi önler. |
Bu mekanizma, Point-in-Time Recovery (PITR) için zemin hazırlar. Düzenli alınan taban yedekleri (base backups) ile sürekli bir WAL arşivi birleştirildiğinde, veritabanı, arşivin kapsadığı herhangi bir işlem noktasına geri yüklenebilir. Arşivleme komutunun güvenilirliği ve hedef depolamanın dayanıklılığı, bu kurtarma yeteneğinin temel belirleyicileridir.
Konfigürasyon ve Uygulama Adımları
Etkin bir WAL arşivleme altyapısının kurulumu, hem PostgreSQL yapılandırmasını hem de operasyonel süreçleri kapsayan sistematik bir yaklaşım gerektirir. İlk adım, `postgresql.conf` dosyasında kritik parametrelerin ayarlanmasıdır. `archive_mode` parametresinin `on` olarak değiştirilmesi sistemin yeniden başlatılmasını gerektirir, bu nedenle genellikle bakım penceresi planlamasını zorunlu kılar. `archive_command` tanımı ise, seçilen depolama çözümüne ve ağ altyapısına bağlı olarak dikkatlce formüle edilmelidir.
`archive_command` için temel bir örnek, WAL segmentlerini ağ üzerindeki paylaşımlı bir NFS dizinine kopyalamak olabilir: `archive_command = 'test ! -f /mnt/wal_archive/%f && cp %p /mnt/wal_archive/%f'`. Bu komutta `test ! -f ...` kısmı, hedef dosyanın zaten var olup olmadığını kontrol ederek idempotent davranışı sağlar. Ancak, daha sağlam ve ölçeklenebilir çözümler için nesne depolama (S3, GCS) kullanımı önerilir. AWS S3 için örnek bir komut şu şekilde olabilir:
archive_command = 'aws s3 cp %p s3://your-bucket/wal-archive/%f --region eu-west-1'
Komutun güvenilirliğini artırmak için, zaman aşımı (timeout) ve hata yönetimi eklemek faydalıdır. Bash script'leri veya `pgbackrest`, `barman` gibi özel araçlar kullanılarak daha karmaşık mantıklar (örn., arşivleme başarısızlıklarında uyarı) uygulanabilir. Yapılandırma sonrası, ayarların etkinliğini doğrulamak adına manuel bir WAL geçişi tetiklenmeli ve arşivleme işleminin başarıyla tamamlandığı kontrol edilmelidir: `SELECT pg_switch_wal();`.
Arşivlemenin sürekli ve hatasız çalıştığından emin olmak için proaktif izleme şarttır. `pg_stat_archiver` görünümü temel bir araçtır. Aşağıdaki sorgu, arşivleme durumunu ve olası birikmeyi gösterecektir.
SELECT archived_count, last_archived_wal, last_archived_time,
failed_count, last_failed_wal, last_failed_time,
now() - last_archived_time AS archive_lag
FROM pg_stat_archiver;
`failed_count`'un sıfır olması ve `last_archived_time`'ın sürekli güncellenmesi beklenir. Artan bir `archive_lag`, depolama hedefinde bir performans sorunu veya ağ tıkanıklığına işaret edebilir. Ayrıca, dosya sistemi alanı da düzenli olarak kontrol edilmelidir; başarısız bir `archive_command`, `pg_wal` dizinini hızla doldurabilir ve veritabanı işlemlerini durdurabilir.
- Adım 1: Planlama ve Gereksinimler: Kurtarma Noktası Hedefi (RPO) ve Bekletme Politikası belirlenmeli. Depolama kapasitesi, ağ bant genişliği ve güvenlik (şifreleme, IAM) gereksinimleri tanımlanmalı.
- Adım 2: PostgreSQL Yapılandırması: `postgresql.conf` dosyasında `archive_mode`, `archive_command`, `archive_timeout` (isteğe bağlı) ve `wal_keep_size` parametreleri ayarlanmalı.
- Adım 3: Depolama Altyapısı Hazırlığı: NFS paylaşımı, S3 kovası veya benzeri hedef depolama oluşturulmalı ve erişim kimlik bilgileri/anahtarları PostgreSQL sunucusunda yapılandırılmalı.
- Adım 4: Doğrulama ve Test: PostgreSQL yeniden başlatılmalı, `pg_switch_wal()` ile manuel test yapılmalı ve `pg_stat_archiver` görünümü ile başarı kontrol edilmeli.
- Adım 5: İzleme ve Bakım: Arşivleme gecikmesi, başarısızlık sayacı ve depolama alanı için otomatik alarmlar kurulmalı. Düzenli olarak kurtarma drills'leri yapılmalı.
Son olarak, WAL arşivleme yalnızca bir yedekleme stratejisinin parçasıdır. Taban yedeklerinin (base backups) düzenli olarak (örn., haftalık) alınması ve bu yedeklerin hangi WAL segmentinden itibaren geçerli olduğunun (`backup_label` dosyası ile) kayıt altına alınması gerekir. Bu, bir kurtarma senaryosunda başlangıç noktasını belirlemek için hayatidir.
Kurtarma Senaryoları ve PITR
WAL arşivlemenin nihai amacı, veri kaybını en aza indiren ve herhangi bir noktaya dönüş imkanı sağlayan kurtarma operasyonlarını mümkün kılmaktır. Point-in-Time Recovery (PITR), bu yeteneğin somutlaşmış halidir. PITR, bir taban yedeğini (base backup) geri yükleyip, ardından arşivlenmiş WAL loglarını, kullanıcının belirttiği bir zaman veya işlem noktasına (LSN) kadar sırayla uygulayarak (replay) çalışır. Bu süreç, veritabanını, arşivin izin verdiği sürece, geçmişteki herhangi bir anlık görüntüye getirir.
Bir tam kurtarma senaryosunun başlatılması için öncelikle çalışan PostgreSQL kümesi durdurulur ve veri dizini (`PGDATA`) boşaltılır veya yeni bir konuma taşınır. Ardından, bir taban yedeği (örneğin `pg_basebackup` aracı ile alınmış) temiz bir veri dizinine çıkarlır. Bu yedeğin içindeki `backup_label` ve `backup.manifest` (PG12+) dosyaları, kurtarmanın hangi WAL segmentinden başlayacağını (`START WAL LOCATION`) belirler. Geri yükleme işlemi, `PGDATA` dizininde bir `recovery.signal` (PG12+) dosyası oluşturularak veya eski sürümlerde `recovery.conf` dosyası konfigüre edilerek başlatılır.
Kurtarma parametrelerinin doğru ayarlanması kritiktir. `restore_command`, arşivleme sırasında kullanılan `archive_command`'ın mantıksal karşılığıdır. Amacı, PostgreSQL kurtarma sürecine istenen WAL segmentlerini sunmaktır. Örneğin, S3'ten WAL getiren bir komut şöyle olabilir: `restore_command = 'aws s3 cp s3://your-bucket/wal-archive/%f %p --region eu-west-1'`. Kurtarmanın nerede duracağını belirlemek için `recovery_target` parametre grubu kullanılır. `recovery_target_time`, `recovery_target_name` (bir restore point), `recovery_target_lsn` veya `recovery_target_xid` belirtilebilir. `recovery_target_inclusive` parametresi ise belirtilen hedefin dahil edilip edilmeyeceğini kontrol eder.
PITR'nin gücü, yalnızca tam felaket kurtarmada değil, aynı zamanda insan hatasının geri alınmasında da yatar. Yanlışlıkla silinen bir tablo veya hatalı bir toplu güncellemeden sonra, veritabanı hatanın hemen öncesindeki bir zamana kurtarılabilir. Bu işlem tipik olarak bir geri yükleme ortamında gerçekleştirilir; kurtarılan veriler daha sonra dışa aktarılarak veya logical replication ile ana veritabanına seçici olarak taşınır. Bu yaklaşım, ana sistemin kapalı kalma süresini (downtime) en aza indirger.
İleri seviye bir senaryo, zaman çizelgesi (timeline) kavramını içerir. Bir PITR gerçekleştirildiğinde, veritabanı yeni bir zaman çizelgesinde (örneğin, orijinal Timeline 1'den Timeline 2'ye) başlatılır. Bu, orijinal WAL arşivinin, kurtarılmış veritabanı tarafından üretilecek yeni WAL segmentleriyle karışmasını önler. Timeline'lar, dallanma noktalarını takip etmeyi ve gerektiğinde önceki bir timeline'a geri dönmeyi mümkün kılar. `pg_wal` dizinindeki WAL dosya isimlerinin ilk 8 hanesi, timeline kimliğini temsil eder.
Kurtarma performansını optimize etmek için bazı önemli noktalar vardır. WAL arşivlerinin kurtarma makinesine yerel bir SSD'ye önceden çekilmesi, ağ gecikmesini ortadan kaldırarak süreyi önemli ölçüde kısaltır. Ayrıca, `recovery_prefetch` ve `wal_decode_buffer_size` (PG13+) gibi parametreler, WAL kayıtlarının önceden okunmasını ve decode edilmesini sağlayarak kurtarma hızını artırabilir. Kurtarma sürecinin ilerlemesi, `pg_stat_recovery_progress` görünümü sorgulanarak gerçek zamanlı olarak izlenebilir; bu görünüm, geri yüklenen WAL boyutu, geçen süre ve tahmini kalan süre gibi metrikleri sunar.
Sonuç olarak, WAL arşivleme ve PITR, PostgreSQL'in sunduğu en güçlü veri koruma katmanını oluşturur. Ancak bu korumanın etkinliği, düzenli ve otomatik testlerle kanıtlanmadıkça varsayılamaz. Kritik sistemler için, aylık veya çeyreklik kurtarma tatbikatları (recovery drills) yapılmalı; bu tatbikatlar sadece dosyaların geri yüklenmesini değil, aynı zamanda uygulama bağlantılarının ve veri bütünlüğünün de doğrulanmasını içermelidir. Bu disiplinli yaklaşım, teorik bir yedekleme planını, garantili bir kurtarma yeteneğine dönüştürür.