Veritabanı Yönetimi

    PostgreSQL Streaming Replikasyon Kurulumu

    Birincil ve yedek PostgreSQL sunucu arasında akış replikasyonu kurmanın tam adımları.

    10 dk okuma Güncellendi: 25 Ağustos 2026

    Tek bir veritabanı sunucusuyla çalışıyorsanız, o makine düştüğü anda hizmetiniz de düşer. Yedeğiniz olsa bile geri yükleme saatler sürebilir ve son yedekle çökme anı arasındaki veri kaybolur. PostgreSQL streaming replikasyon, bu iki problemi birden çözer: birincil sunucudaki her değişikliği WAL akışı üzerinden ikinci bir makineye anlık olarak taşır, böylece her an güncel bir kopyanız olur ve bu kopya aynı zamanda okuma sorgularınızı da karşılayabilir.

    Bu rehberde iki sunucu arasında sıfırdan akış replikasyonu kuracağız. Birincil sunucunun nasıl hazırlanacağını, pg_basebackup ile yedek sunucunun nasıl klonlanacağını, replikasyon yuvasının neden hayati olduğunu, gecikmenin nasıl izleneceğini ve gerçekten devir alma (failover) gerektiğinde ne yapılacağını anlatacağım. Örneklerde birincil sunucu 185.12.34.56, yedek sunucu 185.12.34.57 olarak geçecek; siz kendi adreslerinizle değiştirin.

    Streaming Replikasyon Nasıl Çalışır#

    PostgreSQL her değişikliği önce WAL'a (Write-Ahead Log) yazar. Akış replikasyonu, bu WAL kayıtlarını birincil sunucudan yedek sunucuya TCP üzerinden sürekli akıtır. Yedek sunucu bu kayıtları uygular ve kendi veri dosyalarını birincilin aynısı hâline getirir. Yedek sunucu kurtarma modunda çalışır: yazma kabul etmez ama sorgu yanıtlayabilir (hot standby).

    İki dayanıklılık modu vardır ve aralarındaki seçim iş kuralınıza bağlıdır:

    Modsynchronous_commitDavranışKayıp riskiPerformans
    Asenkronlocal veya on (yuva tanımsız)Birincil, yedeği beklemeden onaylarSon işlemler kaybolabilirEn hızlı
    Senkronon + synchronous_standby_namesYedek yazdığını doğrulayana kadar beklerNeredeyse sıfırAğ gecikmesi kadar yavaş
    Uzlaşmaremote_writeYedeğin işletim sistemine ulaşması yeterliÇok düşükOrta

    Varsayılan ve çoğu senaryoda doğru olan asenkron moddur. Senkron replikasyon, yedek sunucu yanıt vermediğinde birincil sunucudaki yazmaların da durmasına yol açar; tek yedekle senkron mod kurmak, erişilebilirliği artırmak yerine azaltabilir. Senkron kullanacaksanız en az iki yedek bulundurun.

    Birincil Sunucuyu Hazırlama#

    İlk iş, replikasyona özel bir kullanıcı oluşturmaktır. Bu kullanıcının veri okuma yetkisi olmasına gerek yoktur; yalnızca REPLICATION özniteliği yeterlidir.

    sudo -u postgres psql -c "CREATE ROLE replikator WITH REPLICATION LOGIN PASSWORD 'GucluBirParola';"
    

    Parolayı elle uydurmak yerine şifre üretici aracımızdan uzun ve rastgele bir değer alın; bu kullanıcı ağ üzerinden kimlik doğrular.

    Ardından postgresql.conf dosyasında replikasyon ayarlarını yapın:

    # /etc/postgresql/16/main/conf.d/20-replication.conf
    listen_addresses = '*'
    wal_level = replica
    max_wal_senders = 10
    max_replication_slots = 10
    wal_keep_size = 1GB
    hot_standby = on
    archive_mode = on
    archive_command = 'test ! -f /var/lib/postgresql/wal_arsiv/%f && cp %p /var/lib/postgresql/wal_arsiv/%f'
    

    wal_level = replica zorunludur; minimal seviyesinde replikasyon için gereken bilgi WAL'a yazılmaz. max_wal_senders, aynı anda kaç yedeğin bağlanabileceğini belirler; pg_basebackup da bir yuva tükettiği için ihtiyacınızdan birkaç fazla verin.

    pg_hba.conf dosyasında yedek sunucuya izin verin. Satırın veritabanı sütununa replication yazılır; bu, gerçek bir veritabanı adı değil, özel bir anahtar kelimedir:

    # TYPE  DATABASE      USER         ADDRESS            METHOD
    host    replication   replikator   185.12.34.57/32    scram-sha-256
    

    Adresi /32 ile tek bir IP'ye kısıtlayın; 0.0.0.0/0 yazmak, veritabanınızın tam bir kopyasını internete açmak demektir. Değişiklikleri uygulayın:

    sudo mkdir -p /var/lib/postgresql/wal_arsiv
    sudo chown postgres:postgres /var/lib/postgresql/wal_arsiv
    sudo systemctl restart postgresql@16-main
    

    wal_level değişikliği yeniden başlatma gerektirir; pg_hba.conf için reload yeterlidir. Diğer bellek ve WAL parametreleri için postgresql.conf optimizasyon rehberi yazısına bakabilirsiniz.

    Replikasyon Yuvası Oluşturma#

    Replikasyon yuvası (replication slot), birincil sunucuya "bu yedek şu ana kadar okudu" bilgisini kalıcı olarak tutturur. Yuva olmadan, yedek sunucu bir süre kapalı kalırsa ihtiyaç duyduğu WAL dosyaları birincilde silinmiş olabilir ve replikasyon onarılamaz biçimde kopar.

    SELECT * FROM pg_create_physical_replication_slot('yedek_01');
    
    -- Yuvaları listele
    SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;
    

    Yuvanın önemli bir yan etkisi var ve bunu bilmemek diski doldurur: yuva aktif olmayan bir yedek için WAL biriktirmeye devam eder. Kalıcı olarak kapatılan bir yedeğin yuvasını mutlaka silin. Ne kadar WAL biriktiğini izlemek için:

    SELECT
        slot_name,
        active,
        pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS biriken_wal
    FROM pg_replication_slots;
    

    PostgreSQL 13 ve sonrasında bu riski sınırlayan bir emniyet valfi var:

    max_slot_wal_keep_size = 10GB
    

    Bu ayarla, bir yuva 10 GB'tan fazla WAL biriktirirse PostgreSQL yuvayı geçersiz kılar ve WAL'ı temizler. Yedek koparsa yeniden klonlarsınız ama diskiniz dolmaz — bu neredeyse her zaman doğru tercihtir. Terk edilmiş yuvaların yol açtığı diğer sorunlar için PostgreSQL VACUUM ve autovacuum yazısındaki temizliği engelleyen etkenler bölümüne göz atın.

    Yedek Sunucuyu Klonlama#

    Yedek sunucuda PostgreSQL'i aynı ana sürümle kurun (16 ile 15 replike olmaz), servisi durdurun ve veri dizinini boşaltın:

    sudo systemctl stop postgresql@16-main
    sudo -u postgres rm -rf /var/lib/postgresql/16/main/*
    

    Şimdi pg_basebackup ile birincilin tam bir kopyasını alın:

    sudo -u postgres pg_basebackup \
      --host=185.12.34.56 \
      --username=replikator \
      --pgdata=/var/lib/postgresql/16/main \
      --slot=yedek_01 \
      --write-recovery-conf \
      --wal-method=stream \
      --checkpoint=fast \
      --progress --verbose
    

    Bayrakların anlamı önemli:

    1. --write-recovery-conf, veri dizinine standby.signal dosyasını ve postgresql.auto.conf içine primary_conninfo satırını otomatik yazar. Bu bayrağı unutursanız sunucu yedek olarak değil, bağımsız birincil olarak açılır ve iki ayrı gerçeklik oluşur.
    2. --wal-method=stream, kopyalama sürerken üretilen WAL'ı da paralel olarak çeker; uzun süren klonlamalarda kaydın eksik kalmasını engeller.
    3. --slot=yedek_01, klonlama boyunca da yuvanın korunmasını sağlar.
    4. --checkpoint=fast, birincilde hemen bir kontrol noktası tetikleyerek beklemeyi kısaltır.

    Parola sorusunu betikte geçmek için ~/.pgpass kullanın; parolayı komut satırına yazmayın:

    sudo -u postgres bash -c "echo '185.12.34.56:5432:replication:replikator:GucluBirParola' > ~/.pgpass && chmod 600 ~/.pgpass"
    

    Kopyalama bitince oluşan dosyaları doğrulayın ve servisi başlatın:

    ls -l /var/lib/postgresql/16/main/standby.signal
    sudo -u postgres grep primary_conninfo /var/lib/postgresql/16/main/postgresql.auto.conf
    sudo systemctl start postgresql@16-main
    

    Yedeğin gerçekten kurtarma modunda olduğunu doğrulayın:

    SELECT pg_is_in_recovery();
    -- t (true) dönmeli
    

    Gecikmeyi İzlemek#

    Replikasyon kurulduktan sonra asıl iş başlar: gecikmeyi izlemek. Birincil sunucudan bakıldığında her yedeğin durumu pg_stat_replication görünümünde görünür:

    SELECT
        application_name,
        client_addr,
        state,
        sync_state,
        pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn))   AS gonderim_farki,
        pg_size_pretty(pg_wal_lsn_diff(sent_lsn, replay_lsn))             AS uygulama_farki,
        write_lag, flush_lag, replay_lag
    FROM pg_stat_replication;
    

    state sütunu streaming olmalıdır; catchup görüyorsanız yedek hâlâ geride kalan kayıtları uyguluyor demektir. Yedek sunucudan bakarken saat cinsinden gecikmeyi ölçmek daha anlaşılırdır:

    SELECT
        now() - pg_last_xact_replay_timestamp() AS gecikme_suresi,
        pg_last_wal_receive_lsn()               AS alinan,
        pg_last_wal_replay_lsn()                AS uygulanan;
    

    Birincilde hiç yazma olmadığı sessiz dönemlerde bu değer artıyormuş gibi görünür; bu yanıltıcıdır. alinan ve uygulanan değerleri eşitse gecikme aslında sıfırdır.

    Gecikmenin iki tipik sebebi vardır. Birincisi ağ bant genişliğinin yetmemesidir: yoğun yazma altında saniyede üretilen WAL miktarı hattınızı doldurabilir. Ne kadar WAL ürettiğinizi kabaca ölçüp bant genişliği hesaplayıcı ile hattınızın yeterli olup olmadığını değerlendirebilirsiniz. İkincisi, yedekte çalışan uzun sorguların WAL uygulamasını engellemesidir; bu durumda max_standby_streaming_delay devreye girer.

    Yedek Sunucuyu Okuma İçin Kullanmak#

    hot_standby = on ayarıyla yedek sunucu okuma sorgularını karşılayabilir. Raporlama, analiz ve arama trafiğini buraya yönlendirmek birincili belirgin biçimde rahatlatır. Ama bir çatışma var: yedek, gelen WAL'ı uygulamak isterken çalışan bir sorgunun ihtiyaç duyduğu satır sürümünü silmek zorunda kalabilir. PostgreSQL bu durumda ya sorguyu iptal eder ya da WAL uygulamasını erteler.

    # Yedek sunucuda
    hot_standby = on
    max_standby_streaming_delay = 30s   # sorgu uğruna en fazla 30 sn geride kal
    hot_standby_feedback = on           # birincile "bu satırları henüz silme" de
    

    hot_standby_feedback = on, sorgu iptallerini büyük ölçüde bitirir ama bir bedeli vardır: birincil sunucu, yedekteki uzun sorgular yüzünden ölü satırları temizleyemez ve şişme başlar. Yedekte saatlerce süren raporlar çalıştırıyorsanız bu ayarı açmak birincilinizi bozabilir. Karar verirken hangi tarafın şişmesine razı olduğunuzu bilerek seçin.

    Uygulama tarafında okuma trafiğini ayırmak için bağlantı dizesinde hedef oturum özniteliği kullanabilirsiniz:

    postgresql://[email protected],185.12.34.57/veritabani?target_session_attrs=read-write
    postgresql://[email protected],185.12.34.56/veritabani?target_session_attrs=any
    

    Bağlantı sayısı arttıkça hem birincil hem yedek tarafta havuz kullanmak gerekir; PgBouncer kurulumu yazısı bu katmanı anlatıyor.

    Devir Alma (Failover) ve Sık Yapılan Hatalar#

    Birincil sunucu çöktüğünde yedeği yükseltmek tek komuttur:

    sudo -u postgres pg_ctl promote -D /var/lib/postgresql/16/main
    # ya da SQL tarafından:
    # SELECT pg_promote();
    

    Yükseltme sonrası yedek, kurtarma modundan çıkar, yeni bir zaman çizgisi (timeline) başlatır ve yazma kabul etmeye başlar. Bu noktada dikkat edilmesi gereken kritik nokta şudur: eski birincili aynı anda geri açmayın. İki sunucu da yazma kabul ederse "split brain" oluşur ve iki veri seti bir daha birleştirilemez.

    Eski birinciyi yeni birincinin yedeği hâline getirmenin doğru yolu pg_rewind'dir; tam bir yeniden klonlamadan çok daha hızlıdır:

    sudo systemctl stop postgresql@16-main
    sudo -u postgres pg_rewind \
      --target-pgdata=/var/lib/postgresql/16/main \
      --source-server="host=185.12.34.57 user=replikator dbname=postgres" \
      --progress
    

    pg_rewind çalışması için birincilde wal_log_hints = on ya da veri sağlama toplamlarının (data checksums) açık olması gerekir. Bunu kurulum aşamasında ayarlayın; çökme anında ayarlamaya çalışmak mümkün değildir.

    Şimdi klasik hatalara gelelim. Yedek almayı bıraktığınızı sanmak en tehlikelisidir: replikasyon yedek değildir. Birincilde yanlışlıkla DELETE FROM musteriler çalıştırırsanız, bu komut saniyeler içinde yedeğe de yansır. Replikasyon donanım arızasına karşı korur, insan hatasına karşı korumaz. Düzenli pg_dump almayı sürdürün; ayrıntı için pg_dump ile yedekleme yazısına bakın.

    Sürüm uyuşmazlığı ikinci klasiktir: fiziksel replikasyonda iki sunucunun ana sürümü aynı olmalıdır. Ana sürüm yükseltmesi yaparken replikasyonu bozmadan geçiş için mantıksal replikasyon veya pg_upgrade planlaması gerekir.

    Yuva temizliğini unutmak üçüncüsüdür. Devre dışı bıraktığınız bir yedeğin yuvası birincilde WAL biriktirmeye devam eder ve haftalar sonra diski doldurup birincili durdurur. Yuvaları düzenli listeleyin, active = false olanları sorgulayın.

    Failover'ı hiç denememek ise en pahalıya patlayanıdır. Devir alma prosedürünü, henüz krizde değilken bir test ortamında baştan sona çalıştırın ve süresini ölçün. MySQL tarafında benzer bir kurulumu karşılaştırmak isterseniz MySQL replikasyon kurulumu yazısı iyi bir referans.

    Sıkça Sorulan Sorular#

    Streaming replikasyon yedekleme yerine geçer mi#

    Hayır, kesinlikle geçmez. Replikasyon donanım arızası ve sunucu kaybına karşı korur; ancak yanlışlıkla silinen bir tablo, bozulan bir veri ya da bir fidye yazılımı saniyeler içinde yedeğe de yansır. Replikasyon "yüksek erişilebilirlik", yedekleme ise "geçmişe dönebilme" çözümüdür. İkisini birlikte kullanın, biri diğerinin yerine geçmez.

    Senkron mu asenkron replikasyon mu seçmeliyim#

    Çoğu senaryoda asenkron doğru seçimdir; birincil sunucu yedeği beklemez, performans etkisi minimumdur ve olası kayıp genelde son birkaç işlemle sınırlıdır. Senkron mod, hiçbir işlemin kaybolmaması gereken finansal sistemler içindir; ancak tek yedekle kurarsanız yedek yanıt vermediğinde birincildeki yazmalar da durur. Senkron kullanacaksanız en az iki yedek bulundurun.

    Replikasyon gecikmesini nasıl kontrol ederim#

    Birincil sunucuda pg_stat_replication görünümüne bakın; state sütunu streaming olmalı ve replay_lag değeri düşük kalmalıdır. Yedek sunucuda ise now() - pg_last_xact_replay_timestamp() ifadesi zaman cinsinden gecikmeyi verir. Sessiz dönemlerde bu değerin artması normaldir; gerçek durumu anlamak için pg_last_wal_receive_lsn() ile pg_last_wal_replay_lsn() değerlerini karşılaştırın.

    Yedek sunucuda sorgu çalıştırabilir miyim#

    Evet, hot_standby = on ayarıyla yedek sunucu okuma sorgularını karşılar ve raporlama yükünü birincilden almak için mükemmeldir. Ancak yazma yapamazsınız ve uzun süren sorgular WAL uygulamasıyla çakışıp iptal edilebilir. max_standby_streaming_delay ile toleransı artırabilir ya da hot_standby_feedback açabilirsiniz; ikincisi birincilde tablo şişmesine yol açabileceği için dikkatli kullanın.

    Replikasyon koptuğunda ne yapmalıyım#

    Önce yedek sunucunun günlüklerine bakın; en yaygın sebep ihtiyaç duyulan WAL dosyalarının birincilde silinmiş olmasıdır. Replikasyon yuvası kullanıyorsanız bu genellikle olmaz. WAL kaybolduysa tek çözüm pg_basebackup ile yeniden klonlamaktır. Ağ ya da kimlik doğrulama sorunuysa pg_hba.conf satırını ve parolayı kontrol edin, sorun giderildiğinde yedek kendiliğinden yeniden bağlanır.

    Farklı PostgreSQL sürümleri arasında replikasyon kurulabilir mi#

    Fiziksel akış replikasyonunda hayır; birincil ve yedek aynı ana sürümü çalıştırmalıdır çünkü veri dosyası biçimi sürümler arasında değişir. Farklı ana sürümler arasında veri akıtmak istiyorsanız PostgreSQL 10 ile gelen mantıksal replikasyonu (logical replication) kullanmanız gerekir; bu yöntem tablo bazında çalışır ve ana sürüm yükseltmelerinde kesintiyi en aza indirmek için tercih edilir.

    Kapanış#

    Streaming replikasyon, PostgreSQL'i tek makinelik bir riskten çıkarıp gerçek bir üretim altyapısına dönüştüren adımdır. Doğru kurulduğunda hem sunucu kaybına karşı sigortanız hem de okuma yükünü dağıtabileceğiniz ikinci bir kaynağınız olur. Aklınızda tutmanız gereken dört alışkanlık: replikasyon yuvası kullanın ama max_slot_wal_keep_size ile diski koruyun, pg_stat_replication üzerinden gecikmeyi izlemeyi otomatikleştirin, wal_log_hints ayarını daha kurulum aşamasında açın ve devir alma prosedürünü kriz anından önce en az bir kez prova edin.

    Replikasyonun sağlığı, iki sunucu arasındaki ağ kalitesine ve disk hızına doğrudan bağlıdır; aynı altyapıda konumlanmış makineler arasında gecikme belirgin biçimde düşer. Birincil ve yedek sunucularınızı kurmak için VDS, bulut sunucu ve daha yüksek yükler için dedicated sunucu seçeneklerimize bakabilirsiniz; kurulum, izleme ve devir alma planını bize bırakmak isterseniz sunucu yönetimi hizmetimiz bu işi üstlenir. Replikasyonun yanına mutlaka yedekleme çözümü de ekleyin.

    PostgreSQLReplikasyonYüksek Erişilebilirlik

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.