Bir veritabanı sunucusu yönetirken er geç kendinize soracağınız tek bir soru vardır: "Bu makine şu an ölse, verimi nereden geri getiririm?" Bu sorunun cevabını felaket anında değil, huzurlu bir salı öğleden sonrasında hazırlamış olmanız gerekir. PostgreSQL, bu iş için son derece olgun ve güvenilir araçlar sunar; pg_dump ve pg_restore ikilisi, yıllardır üretim ortamlarında milyonlarca veritabanını sorunsuzca yedekleyip geri getiren, standartlaşmış çözümlerdir. Doğru kullanıldığında, bir veritabanını başka bir sunucuya taşımaktan versiyon yükseltmesine, tek bir tabloyu kurtarmaktan tüm kümeyi klonlamaya kadar her senaryoyu karşılarlar.
Bu rehberde pg_dump ile düz SQL ve custom format (-Fc) yedek almayı, pg_restore ile seçmeli geri yüklemeyi, pg_dumpall ile rollerle birlikte tüm kümeyi yedeklemeyi, sıkıştırma tekniklerini ve cron ile gecelik otomatik yedek kurmayı uygulamalı örneklerle ele alacağız. Mantıksal ve fiziksel yedeğin farkına da kısaca değinerek hangi durumda hangisini seçmeniz gerektiğini netleştireceğiz. Örnek komutları kendi sunucunuzda birebir çalıştırabilir, veritabanı adlarını ve yollarını kendi ortamınıza göre uyarlayabilirsiniz. Henüz kurulum tarafındaysanız Ubuntu'da PostgreSQL kurulumu yazımız iyi bir başlangıç noktasıdır.
Mantıksal Yedek ile Fiziksel Yedek Farkı#
Yedekleme stratejinizi kurmadan önce iki temel yaklaşımı ayırt etmeniz gerekir, çünkü bu seçim aracınızı ve tüm iş akışınızı belirler.
Mantıksal yedek (logical backup), pg_dump'ın yaptığı iştir. Veritabanını okur ve onu yeniden oluşturmak için gereken CREATE TABLE, INSERT ya da COPY gibi SQL komutlarını üretir. Sonuç, veritabanının "tarifidir"; hangi PostgreSQL sürümüne, hangi işletim sistemine, hatta hangi CPU mimarisine geri yükleyeceğiniz fark etmez. Bu yüzden sürüm yükseltmelerinde (örneğin PostgreSQL 14'ten 16'ya geçerken) ve sunucu taşımalarında ilk tercih mantıksal yedektir. Dezavantajı ise büyük veritabanlarında yavaş olması ve alındığı anın tutarlı görüntüsünü verse de sürekli (point-in-time) kurtarma sunmamasıdır.
Fiziksel yedek (physical backup), veri dizinindeki (PGDATA) gerçek dosyaların bayt bayt kopyasıdır. pg_basebackup ile alınır ve WAL (Write-Ahead Log) arşivlemesiyle birleştirildiğinde, veritabanını belirli bir zamana geri sarabildiğiniz güçlü bir kurtarma altyapısı kurar. Terabaytlarca veriyi olan büyük sistemler için tek mantıklı yol çoğu zaman budur, ama karşılığında aynı PostgreSQL ana sürümüne ve aynı platforma bağımlıdır; kurulumu ve yönetimi daha karmaşıktır.
| Özellik | Mantıksal (pg_dump) | Fiziksel (pg_basebackup) |
|---|---|---|
| İçerik | SQL komutları | Ham veri dosyaları |
| Sürümler arası taşınabilirlik | Evet | Hayır (aynı ana sürüm) |
| Tek tablo/şema kurtarma | Kolay | Zor/imkânsız |
| Büyük veritabanında hız | Yavaş | Hızlı |
| Point-in-time recovery | Hayır | Evet (WAL ile) |
| Kurulum karmaşıklığı | Düşük | Yüksek |
Bu rehberin odağı mantıksal yedektir; çünkü küçük ve orta ölçekli web uygulamalarının, WordPress dışı PHP/Python/Node projelerinin ve çoğu SaaS ürününün ihtiyacını fazlasıyla karşılar. Yüzlerce gigabaytı aşan sistemlerde fiziksel yedeğe geçmenin zamanı geldiğinde ise deneyimli bir ekiple planlamanız akıllıca olur.
pg_dump ile Düz SQL Yedek Alma#
En basit ve en okunabilir yedek biçimi düz SQL dosyasıdır. pg_dump, varsayılan olarak sonucu standart çıktıya (stdout) yazar, bu yüzden bir dosyaya yönlendirmeniz gerekir.
# uygulama_db veritabanını düz SQL olarak yedekle
pg_dump -U postgres uygulama_db > uygulama_db.sql
Komutu genellikle postgres sistem kullanıcısı olarak ya da uygun yetkilere sahip bir rolle çalıştırırsınız. Uzak bir sunucuya bağlanmanız gerekiyorsa -h ve -p bayraklarını ekleyin; parola sormasını istiyorsanız -W kullanabilirsiniz.
pg_dump -h 10.0.0.5 -p 5432 -U yedek_kullanicisi -W uygulama_db > uygulama_db.sql
Bu düz SQL dosyasını doğrudan psql ile geri yüklersiniz; pg_restore gerektirmez. Bu, düz formatın en büyük avantajıdır: dosyayı bir metin editörüyle açıp içine bakabilir, tek bir INSERT satırını değiştirebilir ya da grep ile arama yapabilirsiniz.
# önce boş hedef veritabanını oluştur
createdb -U postgres uygulama_db_yeni
# yedeği geri yükle
psql -U postgres uygulama_db_yeni < uygulama_db.sql
Sık kullanacağınız birkaç faydalı bayrak vardır. --schema-only yalnızca yapıyı (tablolar, indeksler, kısıtlar) alır, veriyi almaz; test ortamı kurarken idealdir. Tam tersi --data-only yalnızca veriyi alır. Belirli bir tabloyu yedeklemek için -t, bir tabloyu hariç tutmak için --exclude-table kullanılır.
# sadece şema (yapı)
pg_dump -U postgres --schema-only uygulama_db > yapi.sql
# sadece "kullanicilar" ve "siparisler" tabloları
pg_dump -U postgres -t kullanicilar -t siparisler uygulama_db > iki_tablo.sql
# log tablosunu hariç tut
pg_dump -U postgres --exclude-table=erisim_kayitlari uygulama_db > uygulama_db.sql
Düz SQL biçimi harika okunur ama iki gerçek sınırlaması vardır: paralel geri yükleme yapamazsınız ve tek bir nesneyi seçip geri getiremezsiniz (dosyanın tamamını çalıştırırsınız). İşte tam bu yüzden üretim ortamları için bir sonraki bölümdeki custom format devreye girer.
Custom Format (-Fc) ve Neden Tercih Etmelisiniz#
pg_dump'ın gerçek gücü custom format (-Fc, "format custom") ile ortaya çıkar. Bu biçim, sıkıştırılmış ikili (binary) bir arşiv üretir ve pg_restore ile birlikte çalışacak şekilde tasarlanmıştır.
# custom format yedek (sıkıştırma varsayılan olarak açık)
pg_dump -U postgres -Fc uygulama_db > uygulama_db.dump
# ya da -f ile dosyayı doğrudan belirt
pg_dump -U postgres -Fc -f uygulama_db.dump uygulama_db
Custom formatın düz SQL'e karşı üç önemli üstünlüğü vardır. Birincisi, dosya otomatik olarak sıkıştırılır (varsayılan gzip), yani ekstra bir gzip adımına gerek kalmadan yer tasarrufu sağlar. İkincisi, geri yükleme sırasında -j bayrağıyla paralel çalışabilir; çok çekirdekli sunucularda büyük veritabanlarını dakikalar yerine saniyeler içinde geri getirir. Üçüncüsü ve en önemlisi, arşivin içindeki nesneleri (tablolar, fonksiyonlar, indeksler) tek tek seçip geri yükleyebilirsiniz. Yani "tüm veritabanını batırmadan sadece silinen bir tabloyu kurtar" senaryosu ancak bu formatla mümkündür.
Bir de directory format (-Fd) vardır; arşivi tek dosya yerine bir dizin içinde birden fazla dosya olarak saklar ve yedek almanın kendisini bile paralelleştirmenize (-j) izin verir. Devasa veritabanlarında yedek süresini ciddi biçimde kısaltır.
# directory format ile 4 paralel iş parçacığıyla yedek
pg_dump -U postgres -Fd -j 4 -f uygulama_db_dir uygulama_db
Bir pratik tavsiye: üretim ortamında düz SQL yerine varsayılan olarak custom formatı kullanın. Okunabilirliği kaybediyor gibi görünseniz de pg_restore -f - ile istediğiniz an SQL'e çevirebilirsiniz, yani hiçbir esnekliği gerçekten kaybetmezsiniz. Karşılaştırmalı bir örnek istiyorsanız MySQL tarafında benzer araçları ele aldığımız MySQL veritabanı yönetimi yazısına da göz atabilirsiniz.
pg_restore ile Geri Yükleme ve Seçmeli Kurtarma#
Custom ya da directory formatta alınmış bir yedeği geri yüklemek için pg_restore kullanılır; düz SQL için değil (onu psql çalıştırır). Temel kullanım şöyledir:
# önce boş hedef veritabanını oluştur
createdb -U postgres uygulama_db_yeni
# yedeği geri yükle
pg_restore -U postgres -d uygulama_db_yeni uygulama_db.dump
Çok çekirdekli bir sunucuda geri yüklemeyi hızlandırmak için -j (jobs) bayrağını kullanın. Örneğin 8 çekirdekli bir makinede -j 4 ile başlamak makul bir seçimdir; indeks ve constraint oluşturma gibi işleri paralel yürütür.
pg_restore -U postgres -d uygulama_db_yeni -j 4 uygulama_db.dump
Asıl sihir seçmeli kurtarmada gizlidir. Diyelim ki bir geliştirici yanlışlıkla siparisler tablosunu sildi, ama diğer her şey yerinde ve canlı veri işliyor. Tüm veritabanını geri yüklemek yerine yalnızca o tabloyu kurtarabilirsiniz:
# yedeğin içindekileri listele (içindekiler tablosu)
pg_restore -l uygulama_db.dump
# sadece "siparisler" tablosunu canlı veritabanına geri yükle
pg_restore -U postgres -d uygulama_db -t siparisler uygulama_db.dump
pg_restore -l komutu, arşivin bir "içindekiler" listesini üretir. Bu listeyi bir dosyaya alıp düzenleyerek (pg_restore -L) tam olarak hangi nesnelerin hangi sırayla geri yükleneceğini kontrol edebilirsiniz; büyük kurtarma operasyonlarında bu cerrahi hassasiyet paha biçilmezdir.
İki bayrağı da bilmekte fayda var. --clean (kısaltması -c), hedefteki nesneleri geri yüklemeden önce DROP eder; bir veritabanının üzerine tazeleme yaparken kullanılır. --if-exists ise bu DROP komutlarını "varsa sil" şeklinde güvenli hale getirir, böylece nesne yoksa hata almazsınız.
pg_restore -U postgres -d uygulama_db --clean --if-exists uygulama_db.dump
Bir de arşivi hiç veritabanına dokunmadan düz SQL'e çevirebilirsiniz; hata ayıklarken ya da tam olarak ne çalışacağını görmek istediğinizde çok işe yarar:
pg_restore -f cikti.sql uygulama_db.dump
pg_dumpall ile Tüm Kümeyi ve Rolleri Yedeklemek#
pg_dump tek bir veritabanını yedekler ama kritik bir şeyi atlar: rolleri (kullanıcılar), parolaları, tablespace tanımlarını ve sunucu genelindeki nesneleri almaz. Yani sadece pg_dump kullanıp yeni bir sunucuya geçtiğinizde, veritabanınız gelir ama ona erişecek kullanıcılar gelmez. Bu, taşıma günü fark edilen klasik bir sürprizdir.
Tüm kümeyi (bir sunucudaki tüm veritabanları + roller) tek seferde almak için pg_dumpall kullanılır:
# tüm kümeyi (roller dahil) tek SQL dosyasına yedekle
pg_dumpall -U postgres > tum_kume.sql
Ancak pg_dumpall her zaman düz SQL üretir; custom formatı desteklemez. Pratikte en dengeli strateji şudur: rolleri ve global nesneleri pg_dumpall --globals-only ile ayrı bir dosyaya, veritabanlarını ise tek tek pg_dump -Fc ile custom formatta almak. Böylece hem rolleri kaybetmezsiniz hem de veritabanlarınızda custom formatın esnekliğini korursunuz.
# sadece roller ve global nesneler (parolalar dahil)
pg_dumpall -U postgres --globals-only > roller.sql
# her veritabanını ayrı custom dump olarak al
for db in uygulama_db blog_db analitik_db; do
pg_dump -U postgres -Fc -f "${db}.dump" "$db"
done
Geri yüklerken önce rolleri kurmanız gerekir, çünkü veritabanlarındaki sahiplik ve yetki tanımları bu rollere bağımlıdır:
# önce rolleri geri yükle
psql -U postgres -f roller.sql
# sonra her veritabanını sırayla kur
createdb -U postgres uygulama_db
pg_restore -U postgres -d uygulama_db uygulama_db.dump
Bu yaklaşım, tam bir sunucu göçünü ya da felaket kurtarmayı temiz ve kontrollü hale getirir. Verilerinizi ve dosyalarınızı sunucular arasında taşırken bütünsel bir yöntem arıyorsanız, dosya sistemi tarafında rsync ile yedekleme rehberimiz veritabanı yedeğini tamamlayan iyi bir eşlikçidir.
Sıkıştırma ve Büyük Veritabanları İçin İpuçları#
Yedek dosyaları hızla büyür ve depolama maliyeti gerçektir. Neyse ki pg_dump sıkıştırmayı doğrudan destekler. Custom ve directory formatlar zaten sıkıştırılmıştır; sıkıştırma seviyesini -Z (0-9 arası) ile ayarlayabilirsiniz. Daha yüksek seviye daha küçük dosya ama daha çok CPU demektir.
# en yüksek sıkıştırma seviyesiyle custom dump
pg_dump -U postgres -Fc -Z 9 -f uygulama_db.dump uygulama_db
Düz SQL yedeklerini ise doğrudan bir pipe ile sıkıştırmak, ara bir dosya oluşturmadan yer kazandırır. gzip her yerde bulunur; daha iyi sıkıştırma ve çok çekirdekli hız isterseniz zstd mükemmel bir tercihtir.
# gzip ile pipe üzerinden sıkıştırılmış SQL yedek
pg_dump -U postgres uygulama_db | gzip > uygulama_db.sql.gz
# zstd ile daha hızlı ve daha iyi oranlı sıkıştırma
pg_dump -U postgres uygulama_db | zstd -T0 -o uygulama_db.sql.zst
Sıkıştırılmış düz yedeği geri yüklerken açıp doğrudan psql'e verirsiniz:
gunzip -c uygulama_db.sql.gz | psql -U postgres uygulama_db_yeni
Büyük veritabanlarında birkaç pratik ilke işinizi kolaylaştırır. Yedeği veritabanının en az yoğun olduğu saatte (genellikle gece) alın; pg_dump okuma kilidi tutmasa da yoğun I/O canlı performansı etkileyebilir. Directory format ve -j ile paralel yedek, çok çekirdekli sunucularda süreyi kat kat kısaltır. Yedekleri asla sadece aynı sunucuda tutmayın; sunucu ölürse yedek de onunla gider. Alınan dosyayı düzenli olarak uzak bir konuma (ayrı bir disk, bir nesne depolama servisi ya da farklı bir veri merkezi) kopyalayın. En önemli ilke ise şudur: test edilmemiş yedek, yedek değildir. Ayda en az bir kez yedeğinizi boş bir test veritabanına geri yükleyip gerçekten çalıştığını kanıtlayın.
Cron ile Otomatik Yedekleme#
Manuel yedek, unutulduğu gün işe yaramaz. Sürdürülebilir tek yol otomasyondur. Aşağıdaki gibi küçük bir betik, custom format yedek alır, dosya adına tarih basar ve belirli bir günden eski yedekleri otomatik olarak temizler.
#!/bin/bash
# /usr/local/bin/pg_yedek.sh
set -euo pipefail
YEDEK_DIZINI="/var/backups/postgres"
VERITABANI="uygulama_db"
TARIH=$(date +%Y-%m-%d_%H%M)
SAKLAMA_GUNU=14
mkdir -p "$YEDEK_DIZINI"
# custom format yedek al
pg_dump -U postgres -Fc -Z 6 \
-f "${YEDEK_DIZINI}/${VERITABANI}_${TARIH}.dump" \
"$VERITABANI"
# 14 günden eski yedekleri sil
find "$YEDEK_DIZINI" -name "${VERITABANI}_*.dump" -mtime +${SAKLAMA_GUNU} -delete
echo "Yedek tamamlandi: ${VERITABANI}_${TARIH}.dump"
Betiği çalıştırılabilir yapın ve postgres kullanıcısının parolasız bağlanabilmesi için ~/.pgpass dosyasını kullanın; böylece parola betiğin içinde açık metin olarak durmaz.
chmod +x /usr/local/bin/pg_yedek.sh
# ~/.pgpass biçimi: sunucu:port:veritabani:kullanici:parola
echo "localhost:5432:uygulama_db:postgres:GIZLI_PAROLA" > ~/.pgpass
chmod 600 ~/.pgpass
Ardından crontab -e ile gecelik bir görev tanımlayın. Aşağıdaki satır betiği her gece saat 03.00'te çalıştırır ve çıktıyı bir log dosyasına yazar:
# her gece 03:00'te veritabanı yedeği
0 3 * * * /usr/local/bin/pg_yedek.sh >> /var/log/pg_yedek.log 2>&1
Cron zamanlama söz dizimini tazelemek isterseniz Linux cron görevleri yazımız beş alanın ne anlama geldiğini adım adım açıklıyor. Otomasyonu kurduktan sonra ilk hafta log dosyasını gözden geçirmeyi ve üretilen dump dosyasının boyutunun beklediğiniz gibi olduğunu doğrulamayı ihmal etmeyin; sessizce başarısız olan bir yedek, felaket anında bulacağınız en kötü sürprizdir.
Kendi sunucusunu yönetmek istemeyenler için yönetilen çözümler işi kökten kolaylaştırır. Clou.TR VDS sunucu ve sanal sunucu paketlerinde tam root erişimiyle bu betikleri istediğiniz gibi kurabilir, dilerseniz sunucu yönetimi hizmetiyle yedekleme dahil tüm bakımı ekibimize bırakabilirsiniz. Sunucu dışı düzenli yedek katmanı için yedekleme çözümlerimiz de ayrı bir güvenlik ağı sağlar.
Sıkça Sorulan Sorular#
pg_dump çalışırken veritabanı kullanılabilir mi?#
Evet, kesinlikle. pg_dump tutarlı bir anlık görüntü (snapshot) alır ve bu sırada tabloları yalnızca paylaşımlı bir kilitle okur; uygulamanız yazma ve okuma işlemlerine devam edebilir. Yani yedek alırken sitenizi bakıma almanıza gerek yoktur. Yalnızca çok büyük veritabanlarında artan disk I/O canlı performansı bir miktar yavaşlatabileceği için yedeği düşük trafikli saatlerde çalıştırmak iyi bir alışkanlıktır.
pg_dump ile pg_dumpall arasındaki fark nedir?#
pg_dump yalnızca tek bir veritabanının içeriğini yedekler ve custom, directory ya da düz SQL biçimlerini destekler. pg_dumpall ise tüm kümeyi, yani sunucudaki bütün veritabanlarını birlikte, ayrıca rolleri, kullanıcı parolalarını ve tablespace gibi global nesneleri de yedekler; ancak yalnızca düz SQL üretebilir. Pratikte en iyi yol ikisini birleştirmektir: rolleri pg_dumpall --globals-only ile, her veritabanını ayrı ayrı pg_dump -Fc ile almak.
Yedeği farklı bir PostgreSQL sürümüne geri yükleyebilir miyim?#
Genellikle evet, çünkü mantıksal yedek SQL komutlarından oluşur ve sürümler arası taşınabilir. Kural olarak, yedeği hedef (yeni) sunucunun pg_dump sürümüyle almak en güvenli yoldur; örneğin PostgreSQL 16'ya geçiyorsanız 16'nın pg_dump aracını kullanarak eski sunucudan yedek alın. Eski bir sürümün aracıyla alınan yedeği çok daha yeni bir sürüme yüklemek çoğunlukla çalışır ama bazı ince uyumsuzluklara yol açabilir, bu yüzden büyük sürüm atlamalarında önce bir test ortamında denemenizi öneririm.
Sadece tek bir tabloyu geri yüklemek mümkün mü?#
Evet, ancak bunun için yedeğinizin custom ya da directory formatta alınmış olması gerekir. Düz SQL yedeğinde nesneleri tek tek seçemezsiniz; dosyanın tamamını çalıştırırsınız. Custom format bir dump'tan tek tablo kurtarmak için pg_restore -d hedef_db -t tablo_adi yedek.dump komutunu kullanırsınız. Bu esneklik, üretim ortamlarında düz SQL yerine custom formatı varsayılan yapmanın en güçlü nedenlerinden biridir.
Yedek dosyamın gerçekten çalıştığından nasıl emin olurum?#
Tek güvenilir yol, yedeği düzenli olarak boş bir test veritabanına geri yükleyip içeriğini kontrol etmektir. Dosyanın var olması ya da boyutunun makul görünmesi yeterli bir kanıt değildir; bozuk ya da yarım bir dump da diskte yer kaplar. Ayda en az bir kez createdb test_db ile boş bir hedef oluşturup yedeği geri yükleyin, ardından birkaç kritik tabloda satır sayısını sorgulayarak beklediğiniz veriyi görün. Bu basit alışkanlık, "yedeğim vardı ama açılmıyor" felaketinden sizi tümüyle korur.
Kapanış#
pg_dump ve pg_restore, PostgreSQL dünyasında yedeklemenin sağlam temelidir. Düz SQL ile okunabilirliği, custom format ile esnekliği ve paralel geri yüklemeyi, pg_dumpall ile de rolleri kaybetmeden tüm kümeyi taşımayı öğrendiniz. Geriye kalan tek adım, bu araçları küçük bir cron betiğine sararak yedeklemeyi unutulmaz bir alışkanlığa dönüştürmek ve aldığınız yedeği düzenli olarak test etmek. Unutmayın: veri kaybının maliyeti her zaman bir yedekleme rutinini kurmanın maliyetinden çok daha yüksektir.
Bu rutini üzerinde huzurla kurabileceğiniz, tam kontrollü bir altyapıya ihtiyacınız varsa Clou.TR yanınızda. Root erişimli VDS ve sanal sunucu paketlerimizle PostgreSQL'i dilediğiniz gibi yapılandırın, uygulamalarınızı web hosting çözümlerimizle yayına alın, kritik verilerinizi yedekleme hizmetimizle ikinci bir katmanda güvence altına alın. Bakım yükünü tümüyle devretmek isterseniz sunucu yönetimi ekibimiz yedekleme dahil her şeyi sizin için üstlenir. Sorularınız için destek ekibimize her an ulaşabilirsiniz.