Teknoloji

MySQL ve PostgreSQL Replikasyonu: VPS’te HA

MySQL ve PostgreSQL Replikasyonunu VPS Üzerinde Neden Ciddiye Almalısınız?

Veritabanı tarafında gerçek anlamda yüksek erişilebilirlik (HA) hedeflediğiniz anda, tek bir VPS veya tek bir fiziksel sunucunun sınırlarına takılırsınız. İster WooCommerce tabanlı bir e-ticaret sitesi, ister SaaS ürünü, ister kurumsal CRM olsun; MySQL veya PostgreSQL veritabanınız birkaç dakika bile erişilemez olduğunda, doğrudan gelir, itibar ve operasyon kaybı yaşanabilir. Proje planlama veya kapasite analizinde yalnızca CPU ve RAM hesaplanıp replikasyon, otomatik failover ve felaket senaryoları ertelenirse, erişilebilirlik gereksinimleri tasarımın dışında kalabilir.

Bu rehberde, VPS üzerinde MySQL ve PostgreSQL replikasyon kurulumu, yüksek erişilebilirlik mimarisi ve otomatik failover mekanizmalarını adım adım ele alacağız. Amaç; replikasyon ve HA tasarımının yapı taşlarını göstermek. Örnekler, üretime geçmeden önce sürüm uyumluluğu, veri tutarlılığı ve arıza davranışı açısından doğrulanması gereken bir başlangıç çerçevesidir. Yedeklemenin replikasyonu, replikasyonun da HA’yı tek başına çözmediğini netleştirip; hangi bileşenin ne işe yaradığını, hangi noktada işin DNS, load balancer ve uygulama katmanına taştığını pratik örneklerle konuşacağız. Bu yapı taşlarını VPS, dedicated sunucu veya colocation ortamlarında değerlendirirken ağ ve fiziksel yerleşim gereksinimlerini seçilen altyapıyla eşleştirmek gerekir.

Komutlar MySQL 8.4 LTS ve PostgreSQL 17 içindir; desteklenen güncel alt sürümleri ve uyumlu istemcileri kullanın. MySQL örnekleri MariaDB’ye doğrudan uygulanmaz. Kurulum öncesinde sürüm, mevcut veri, yedek geri yükleme, sertifika, erişim ve bakım planını doğrulayın. Bağımsız replikasyon ile Patroni tarafından yönetilen cluster, farklı yaşam döngüleridir.

Temel Kavramlar: Yedek, Replikasyon, HA ve Otomatik Failover

Replikasyon kurulumuna girmeden önce, sık karıştırılan birkaç kavramı netleştirmek gerekiyor. Özellikle yönetim tarafıyla konuşurken terimleri doğru kullandığınızda, bütçe ve tasarım kararlarını savunmak çok daha kolaylaşır.

Yedek (Backup) vs Replikasyon

Yedek, belirli bir andaki verinizin kopyasıdır. Amaç; veri kaybı veya hatalı silme durumunda, geçmişe geri dönebilmektir. Genellikle RPO/RTO hedeflerine uygun şekilde, saatlik/günlük/haftalık olarak alınır.

Replikasyon ise veritabanındaki değişikliklerin başka bir sunucuya anlık veya anlığa yakın olarak aktarılmasıdır. Amacı:

  • Okuma yükünü dağıtmak (read scaling)
  • Bir veritabanı sunucusu arızalandığında, diğerini devreye almak (HA/failover)
  • Bazen de bölgesel felaket dayanıklılığı sağlamak (DR/geo-replikasyon)

Yani yedekler geçmişe dönüş içindir, replikasyon ise anlık süreklilik için. Bu konuyu daha derinlemesine ele aldığımız uygulama-tutarlı MySQL/PostgreSQL yedekleri almak rehberini mutlaka bu yazıyla birlikte düşünün.

Yüksek Erişilebilirlik (HA) ve Failover

Yüksek erişilebilirlik, sisteminizin planlanmamış kesintilere rağmen belirli bir yüzdede (ör. %99.9) çalışır kalması hedefidir. Bu hedefe ulaşmak için genellikle şu bileşenler birlikte tasarlanır:

  • Veritabanı replikasyonu (MySQL / PostgreSQL)
  • Otomatik lider seçimi ve failover mekanizması
  • Uygulama ile veritabanı arasına koyulan akıllı bir katman (proxy, load balancer veya DNS)
  • İzleme, alarm ve manuel müdahale için net bir runbook

Bu kavramları daha üst düzeyde ele aldığımız Yüksek kullanılabilirlik (HA) nedir yazısı, stratejik çerçeveyi kurmanıza yardımcı olacaktır. Burada ise doğrudan MySQL ve PostgreSQL üzerinde teknik uygulamaya odaklanacağız.

Senkronsuz vs Senkron Replikasyon

Onayın hangi aşamada verildiğini üç başlıkta ayıralım:

  • Asenkron: primary, replica onayını beklemeden işlemi yerel olarak commit eder. Arızada henüz güvenli biçimde ulaşmamış işlemler kaybolabilir; gecikme için üst sınır yoksa kaybın birkaç saniyeyle sınırlı kalacağı söylenemez.
  • MySQL yarı senkron: gereken replica sayısının olayları relay log’a yazıp diske flush etmesini bekler; olayların uygulanmasını beklemez. Zaman aşımında asenkrona dönebilir.
  • PostgreSQL senkron: onayın anlamını synchronous_commit belirler. on uzak WAL’ın kalıcı depoya flush edilmesini, remote_write işletim sistemine yazılmasını, remote_apply ise kalıcı yazım ve replay’i bekler. synchronous_standby_names ve doğru failover adayı ayrıca gereklidir.

VPS ortamlarında asenkron veya yarı-senkron seçenekleri değerlendirirken ağ gecikmesi, disk I/O ve CPU maliyetlerini RPO/RTO hedefleriyle birlikte ele almak gerekir; yalnızca maliyete göre karar verilmemelidir.

VPS Üzerinde Örnek HA Mimarisi: 2+1 Yaklaşımı

Örnek olarak iki veritabanı VPS’i ve bir yardımcı VPS’ten oluşan 2+1 yerleşimini ele alalım:

  • VPS1: PostgreSQL + Patroni + etcd üyesi 1.
  • VPS2: PostgreSQL + Patroni + etcd üyesi 2.
  • VPS3: etcd üyesi 3; isteğe bağlı proxy veya izleme. Tek proxy bu yerleşimde hâlâ tek hata noktasıdır.

Üçüncü node’un çoğunluk kararına katılması, seçilen HA aracının quorum tasarımına bağlıdır; yalnızca üçüncü bir VPS eklemek split-brain (iki tarafın da kendini lider sanması) riskini ortadan kaldırmaz. Mümkünse VPS’lerinizin aynı veri merkezinde ama farklı fiziksel host’larda konumlanmasını, disk tarafında NVMe depolama kullanılmasını ve özel bir iç ağ üzerinden konuşmasını öneriyoruz.

Bu yerleşimde etcd çoğunluğu 3 üyeden 2’sidir; iki PostgreSQL veri düğümüyle karıştırılmamalıdır. etcd’yi yalnızca VPS3’e kurmak dağıtık quorum oluşturmaz. Bir veri düğümü kaybedildiğinde yalnız bir veri kopyası kalır; iki kopyaya kalıcı senkron yazım şartı varsa yeni yazılar durabilir. DCS, disk, ağ ve proxy arızalarını ayrı test edin. MySQL için Orchestrator’ın kendi Raft denetleyicileri farklı bir mimaridir; PostgreSQL Patroni bileşeni değildir.

Eğer coğrafi yedeklilik düşünüyorsanız, bu şablonu farklı bölgelerdeki veritabanı cluster’larıyla birleştirip, çok bölgeli veritabanı mimarileri yazımızdaki DNS ve geo-routing stratejileriyle zenginleştirebilirsiniz.

MySQL Üzerinde Primary–Replica Replikasyon Kurulumu

Örnek, GTID zaten etkin bir MySQL 8.4 kaynağından yeni ve uygulama trafiğine kapalı bir replica hazırlamayı gösterir. Çalışan GTID dışı bir sistemi dönüştürmek ayrı bir geçiş planı gerektirir.

  • Primary: 10.0.0.1; sertifikada karşılığı bulunan db1.internal.example.com.
  • Replica: 10.0.0.2; sertifikada karşılığı bulunan db2.internal.example.com.

Dağıtımın paket kaynağı, etkin yapılandırma dosyası ve servis adı farklı olabilir. Her düğümde sürümü, benzersiz server_id ve server_uuid değerlerini doğrulayın; fiziksel kopyayla aynı sunucu kimliğini çoğaltmayın. Örnek /secure dizini önceden oluşturulmuş, yalnız yetkili yedek operatörünün eriştiği bir alandır.

1. MySQL Kurulumu ve Temel Güvenlik

MySQL 8.4 kurulu, yönetici erişimi doğrulanmış ve CA tarafından imzalanmış sunucu sertifikaları hazırlanmış olmalıdır. TLS’in hem şifrelemeyi hem bağlanılan sunucunun kimliğini doğruladığını test edin. Aşağıdaki parolalar yer tutucudur; gerçek sırları komut satırı argümanlarına, paylaşılan geçmişe veya loglara yazmayın.

  • İstemcilerin yalnızca uygulama sunucularından ve replikasyon sunucularından bağlanmasına izin verin.
  • MySQL portunu (varsayılan 3306) dış dünyaya açmayın; iç ağda da erişimi güvenlik duvarıyla yetkili sunuculara sınırlandırın.

2. Primary (VPS1) Üzerinde Replikasyon Ayarları

Primary sunucunun my.cnf (veya mysqld.cnf) dosyasında temel ayarları yapın:

[mysqld]
server_id = 1
log_bin = mysql-bin
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
log_replica_updates = ON
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
read_only = OFF
super_read_only = OFF

Bakım penceresinde ayarları dağıtımınıza uygun yöntemle etkinleştirip gerçek değişken değerlerini kontrol edin. Kaynakta, yalnız replica’nın bağlanacağı gerçek çıkış IP’sine izin veren hesabı oluşturun; NAT varsa sunucunun gördüğü adresi kullanın. Bu hesaba yalnız REPLICATION SLAVE gerekir; izleme yetkilerini ayrı hesapta tanımlayın. SQL’i korumalı yönetim oturumunda gerçek bir sırla hazırlayın.

CREATE USER 'repl'@'10.0.0.2'
  IDENTIFIED WITH caching_sha2_password BY 'REPLACE_WITH_UNIQUE_SECRET'
  REQUIRE SSL;
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.0.2';

CREATE USER/GRANT sonrasında FLUSH PRIVILEGES gerekmez. MySQL 8.4’ün caching_sha2_password hesabı burada kimliği doğrulanmış TLS kullanır; RSA anahtarı almaya güvenerek şifresiz bağlantıya dönülmez. Replikasyon parolası replica metadata’sında tutulur; veri dizini ve yedek erişimini kısıtlayın.

İlk veri kopyası ile GTID geçmişi aynı tutarlı durumu temsil etmelidir. Örnekte appdb tek uygulama şemasıdır; birden fazla uygulama şeması varsa hepsini aynı dump işleminde –databases listesine ekleyin. Bir şemayı atlayıp tüm kaynak GTID’lerini uygulanmış saymak eksik veriyi gizler. Kullanıcılar, roller, grants ve DEFINER hesapları sistem tablolarını körlemesine yüklemeden ayrıca envanterlenip replica üzerinde uyumlu hazırlanmalıdır.

umask 077
mysqldump --host=db1.internal.example.com --user=backup --password \
  --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/mysql/ca.pem \
  --single-transaction --quick --source-data=2 --set-gtid-purged=ON \
  --routines --triggers --events --hex-blob --no-tablespaces \
  --databases appdb > /secure/replica-seed.sql

Dump boyunca tüm uygulama tabloları InnoDB olmalı; DDL, hesap/yetki değişiklikleri ve şema dağıtımları durdurulmalıdır. –single-transaction tek başına MyISAM/MEMORY tablolarını tutarlı kılmaz. –source-data=2 başlangıçta kısa bir global okuma kilidi alır ve snapshot’a ait File/Position bilgisini SQL yorumu olarak yazar; bu aşama yazıları bekletebilir. Yedek hesabının SELECT, SHOW VIEW, TRIGGER ve kullanılan seçeneklere göre RELOAD, REPLICATION CLIENT, EVENT ve rutin erişimi gibi yetkilerini resmi mysqldump belgesiyle doğrulayın. –no-tablespaces tablespace tanımlarını dışlar; genel tablespace kullanan sistemler için ayrı geri yükleme tasarımı gerekir.

Komutun çıkış kodu başarılı olmalı; stderr’i ve dump’ın tamamlandığını kontrol edin, dosya hash’ini kaydedin ve geri yüklemeyi sınayın. –set-gtid-purged=ON, kaynak GTID kümesini ve yükleme sırasında sql_log_bin=0 ayarını dump’a ekler. Sistem tablolarını içeren –all-databases dump’ını bu GTID örneğine körlemesine eklemeyin. Hedefte mevcut iş yükü veya örtüşen GTID varsa işlemi durdurup ayrı bir taşıma planı hazırlayın.

File/Position ile alternatif başlangıç ve kilit oturumu

GTID otomatik konumlandırma kullanmayan ayrı bir kanal tasarımında snapshot’ın kendi File/Position çiftini kullanın; daha önce rastgele alınmış bir SHOW çıktısını başka dump’la birleştirmeyin. MySQL 8.4 komutu SHOW BINARY LOG STATUS’tur. Elle FLUSH TABLES WITH READ LOCK kullanılıyorsa aşağıdaki SQL’in çalıştığı istemci oturumu, diğer oturumda koordinatlar okunup tutarlı yedek tamamlanana kadar açık kalmalıdır.

FLUSH TABLES WITH READ LOCK;

İkinci SQL oturumunda, kilit hâlâ tutulurken:

SHOW BINARY LOG STATUS\G

Yedek tamamlandıktan veya kontrollü olarak iptal edildikten sonra, kilidi alan aynı oturumda:

UNLOCK TABLES;

mysql -e ile kilit alıp istemciden çıkmak kilidi bırakır; sonraki yedek bu kilitle korunmaz. Dosya/konum kanalında SOURCE_AUTO_POSITION=0 ve aynı snapshot’tan gelen SOURCE_LOG_FILE/SOURCE_LOG_POS kullanılır. Aşağıdaki ana yol GTID kullanır ve bu seçeneklerle karıştırılmaz.

3. Replica (VPS2) Üzerinde İlk Senkronizasyon

Replica tarafında my.cnf ayarlarını yapın:

[mysqld]
server_id = 2
log_bin = mysql-bin
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
log_replica_updates = ON
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
read_only = ON
super_read_only = ON
relay_log = relay-bin
event_scheduler = OFF

Bu replica ileride primary olabilsin diye log_bin ve log_replica_updates açık tutulur. GTID kullanmanın kendisi her replica’da binary log zorunluluğu oluşturmaz; burada seçim promotable düğüm tasarımına aittir.

Dump’ı şifreli kanaldan taşıyın ve hash’ini karşılaştırın. Hedef yalnız bu kurulum için ayrılmış olmalı; çalışan kanal ve uygulama bağlantıları kapalı, yedek ve hesap envanteri hazır olmalıdır. Dump’taki gtid_purged işlemlerinin hedef geçmişiyle uyumunu ve seed_admin yetkilerini kontrol edin. Yükleme için hedefte super_read_only/read_only korumalarını kontrollü kaldırmak gerekebilir; bu sırada ağ ve hesap düzeyinde uygulama yazılarını kapalı tutun. Mevcut veriyi silmeyin, GTID geçmişini sıfırlamayın.

Hedefe ayrı hesap/DEFINER hazırlığı yaparken gereksiz yerel GTID üretmeyin; yetkili operatör bu kontrollü hazırlık oturumunun sql_log_bin politikasını ve son GTID kümesini doğrulamalıdır. İleride yön tersine dönecekse replikasyon hesabının host kısıtı yeni replica’nın gerçek IP’sine göre ayrıca hazırlanır; geniş bir wildcard ile açılmaz.

Seed başlamadan replica’nın event_scheduler=OFF değerini ve yerel zamanlanmış işlerin kapalı olduğunu doğrulayın. Ağdaki uygulama bağlantılarını kapatmak yerel event/job çalışmasını engellemez. Dump ile gelen event tanımlarını etkinleştirme kararı, yalnız yeni primary’nin tek görev sahibi olduğu doğrulanınca promotion runbook’unda verilmelidir.

mysql --host=db2.internal.example.com --user=seed_admin --password \
  --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/mysql/ca.pem \
  < /secure/replica-seed.sql

Yükleme hatasız bitmeden devam etmeyin. Şema, satır sayısı, uygulama değişmezleri ve DEFINER/grant uyumunu doğrulayın; hedefte read_only=ON ve super_read_only=ON korumalarını yeniden etkinleştirip gerçek değerleri kontrol edin. Çalışır bir kanal varsa aşağıdaki CHANGE işleminden önce her iki replikasyon thread’i durmalıdır.

Yeni replica’da CA dosyası MySQL tarafından okunabilir olmalı ve SOURCE_HOST sertifika adıyla eşleşmelidir. Korumalı SQL oturumunda gerçek sırrı girerek GTID kanalını yapılandırın:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = 'db1.internal.example.com',
  SOURCE_USER = 'repl',
  SOURCE_PASSWORD = 'REPLACE_WITH_UNIQUE_SECRET',
  SOURCE_AUTO_POSITION = 1,
  SOURCE_SSL = 1,
  SOURCE_SSL_CA = '/etc/mysql/ca.pem',
  SOURCE_SSL_VERIFY_SERVER_CERT = 1;
START REPLICA;
SHOW REPLICA STATUS\G

Durumu kontrol etmek için:

SHOW REPLICA STATUS\G

Replica_IO_Running ve Replica_SQL_Running alanları Yes olmalı; Last_IO_Error, Last_SQL_Error ve Performance Schema worker hataları da incelenmelidir. Auto_Position=1, Source_SSL_Allowed/Source_SSL_Verify_Server_Cert ve CA yolunu doğrulayın. Seconds_Behind_Source=0 yalnız başına yetiştiğini veya veri kaybı olmayacağını kanıtlamaz; yavaş ağda receiver gerideyken yanıltıcı olabilir. GTID kümelerini ve uygulama doğrulamasını birlikte değerlendirin. Kaynak gerekli binlog’u silmişse yeni tutarlı seed veya eksik geçmişin güvenilir kaynağı gerekir; auto-position’ı kapatıp hatayı atlamayın.

İsteğe bağlı yarı senkron replikasyon

8.4’te kaynak eklentisi rpl_semi_sync_source, replica eklentisi rpl_semi_sync_replica’dır. Uyumlu eklentiler kurulduktan sonra kaynakta rpl_semi_sync_source_enabled=ON, replica’da rpl_semi_sync_replica_enabled=ON kullanılır; çalışan replica receiver thread’i yeniden bağlanarak yarı senkron yeteneğini kaydeder. Etkin durum, ack sayısı, timeout ve wait point davranışını yük altında test edin. Ack, relay log’un diske flush edilmesidir; SQL apply onayı değildir. Timeout asenkrona dönüşe yol açabildiğinden bunu koşulsuz RPO=0 olarak sunmayın.

4. Otomatik Failover için Basit Yaklaşım

Lider seçimi, eski yazıcının durdurulması ve istemci yönlendirme ayrı görevlerdir. Orchestrator topoloji/failover yönetebilir; ProxySQL veya HAProxy yönlendirme yapar. MySQL Router’ın InnoDB Cluster entegrasyonu klasik iki düğümlü replikasyonda tek başına lider seçimi yerine geçmez. openark/orchestrator deposu arşivlenmiştir ve README bakım için Percona fork’una yönlendirir; yeni kurulumda seçilen dağıtımın 8.4 uyumluluğunu, bakımını ve destek kapsamını doğrulayın.

  • Orchestrator/Raft tercihinde quorum, veritabanı sayısının değil Orchestrator denetleyicilerinin çoğunluğudur; örneğin üç denetleyiciden ikisi. VPS3’te tek süreç denetleyici HA’sı sağlamaz.
  • Primary kaybını birden fazla sinyalle doğrulayın, uygulama yazılarını durdurun ve eski primary’yi ağ/altyapı fencing ile yeni yazı kabul edemeyecek duruma getirin. read_only veya super_read_only tek başına dış fencing değildir.
  • Uygun replica’yı GTID geçmişi, eksik işlemler, apply hataları ve kabul edilen RPO ile seçin; gerekli relay log işlemlerini uygulatın. Yeniden kurulacak kanala ait bilgileri silmeden kaydedin.
  • Promosyon yetkili runbook tarafından tamamlanıp tek yazıcı doğrulandıktan sonra proxy/VIP/DNS hedefini değiştirin; istemci yeniden bağlanmasını ve belirsiz commit sonuçlarını yönetin.

MySQL Group Replication ve InnoDB Cluster farklı bir HA yaklaşımıdır. InnoDB Cluster varsayılan olarak single-primary çalışır; multi-primary isteğe bağlıdır. Üyelik/quorum, uyumluluk ve MySQL Router planı ayrıca tasarlanır. Galera tabanlı ürünler aynı yapılandırmayla kurulmaz; kullanılan ürün ve sürümün belgelerini izleyin.

İlgili rehber: MySQL için gelişmiş HA çözümleri.

PostgreSQL Streaming Replikasyon ve Patroni ile HA

PostgreSQL 17’de fiziksel streaming replication veri akışını, Patroni ise kendi yönettiği cluster’da lider yaşam döngüsünü ve failover kararlarını düzenler. Aşağıdaki ilk adımlar bağımsız primary/standby içindir; Patroni’ye geçiş, çalışan servise ikinci bir yönetici eklemek şeklinde yapılmaz.

1. Temel PostgreSQL Kurulumu ve Ayarlar

Her iki düğüm PostgreSQL 17’nin uyumlu güncel alt sürümlerini kullanmalıdır; fiziksel replikasyon farklı major sürümler arasında yükseltme yöntemi değildir. Primary pg1.internal.example.com / 10.0.0.1, standby pg2.internal.example.com / 10.0.0.2 olarak ele alınır. Sunucu TLS sertifikaları, anahtar izinleri, istemci CA dosyası ve dahili DNS önceden hazırlanmalıdır.

postgresql.conf üzerinde:

listen_addresses = '10.0.0.1'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
max_slot_wal_keep_size = '10GB'
hot_standby = on
password_encryption = 'scram-sha-256'
ssl = on
ssl_cert_file = '/etc/postgresql/tls/server.crt'
ssl_key_file = '/etc/postgresql/tls/server.key'

10GB WAL sınırı yalnız boyutlandırma örneğidir; yazma hızı ve tolere edilecek kesintiye göre ölçün. Slot limiti gerekli WAL’ı korumaya yetmezse standby yeniden seed gerektirebilir; limitsiz slot ise diski doldurabilir. Standby’de listen_addresses ve sertifikayı kendi kimliğine göre değiştirin, max_wal_senders gibi standby kısıtlarını primary ile uyumlu tutun. Başlatma gerektiren parametreleri uygun bakım planıyla etkinleştirin.

Streaming replication için WAL arşivlemesi zorunlu değildir. PITR için ayrıca test edilmiş bir pgBackRest repository/stanza kurulumundan sonra şu arşivleme ayarları kullanılabilir:

archive_mode = on
archive_command = 'pgbackrest --stanza=app archive-push %p'

app stanza’sı, off-host repository, yetkiler ve saklama politikası önceden tanımlanmalı; stanza-create, check, tam yedek ve geri yükleme doğrulanmalıdır. check bir WAL switch tetikleyebilir. Kör cp komutu veya dosya zaten var diye başarı dönmek güvenilir arşiv değildir; tekrar deneme, aynı içeriği doğrulama, çakışma ve disk dolması davranışları önemlidir. WAL arşivi tek başına base backup yerine geçmez.

pg_hba.conf içinde replikasyon yetkisi vereceğiniz replica IP’sini ekleyin:

hostssl replication repl 10.0.0.2/32 scram-sha-256

pg_hba.conf ilk eşleşen kuralı kullanır; önceki geniş host kuralları bu politikayı aşmamalıdır. ssl=on ve okunabilir sunucu sertifikası/anahtarı gerekir. 5432’yi yalnız gerekli iç ağ kaynaklarına açın. Kural ve parola değişikliklerini etkinleştirip gerçek bağlantıda TLS ve SCRAM kullanımını doğrulayın.

Yetkili bir psql oturumunda rolü oluşturun; \password istemi parolayı açık SQL metnine yazmadan atar. Mevcut rolü yeniden oluşturmaya çalışmayın; mevcut hash’i değiştirmek planlı bir parola rotasyonudur.

SET password_encryption = 'scram-sha-256';
CREATE ROLE repl WITH LOGIN REPLICATION;
\password repl

2. Replica İçin Base Backup Alma

Standby için kullanılacak PostgreSQL süreci durmalı ve hedef dizin yeni/boş olmalıdır. Mevcut veri dizinini temizleme komutu çalıştırmayın; gereken veriyi ve ayarları koruyup ayrı bir hedef hazırlayın. Komutu postgres işletim sistemi hesabıyla çalıştırın; /var/lib/postgresql/17/replica sahibi postgres, izinleri 0700 olmalıdır. /var/lib/postgresql/.pgpass dosyası aynı hesapta 0600 izinli olmalı; pg1.internal.example.com:5432:replication:repl:GERÇEK_SIR satırı ve gerekiyorsa kaçışlar güvenli biçimde hazırlanmalıdır.

pg_basebackup \
  --dbname="host=pg1.internal.example.com port=5432 user=repl application_name=standby1 sslmode=verify-full sslrootcert=/etc/postgresql/tls/ca.crt passfile=/var/lib/postgresql/.pgpass" \
  --pgdata=/var/lib/postgresql/17/replica \
  --format=plain --wal-method=stream --write-recovery-conf \
  --create-slot --slot=replica1 --progress

–create-slot için replica1 henüz var olmamalıdır; mevcut slotu incelemeden silmeyin. –wal-method=stream yedek ve WAL için iki walsender bağlantısı kullanır. Ek tablespace varsa hedef yollarını ve –tablespace-mapping gereksinimini önceden doğrulayın. Yarım kalan yedek sonrası kalmış slotları ve WAL disk kullanımını inceleyin; slotu yalnız artık tüketen yoksa kontrollü kaldırın. –write-recovery-conf, standby.signal oluşturur ve bağlantı/slot ayarlarını postgresql.auto.conf içine yazar. PostgreSQL 17’de recovery.conf kullanılmaz.

Başlatmadan önce kopyalanan ve dağıtımda veri dizini dışında tutulan ayarları inceleyin; veri yolu, standby kimliği, TLS, listen_addresses ve hot_standby uyumunu doğrulayın. Doğru standalone servis yöneticisiyle başlatın. Primary’de pg_stat_replication, standby’de pg_is_in_recovery(), pg_stat_wal_receiver ve receive/replay LSN değerlerini inceleyin.

İsteğe bağlı PostgreSQL senkron modu

synchronous_commit = on
synchronous_standby_names = 'FIRST 1 (standby1)'

standby1, yukarıdaki application_name ile eşleşir. Bu standby yoksa ilgili commit’ler bekleyebilir. on kalıcı uzak flush’ı, remote_write yalnız uzak işletim sistemi yazımını, remote_apply ise flush ve replay’i bekler. Boş synchronous_standby_names uzak onay sağlamaz; işlem başına synchronous_commit değişikliği ve yanlış replica’yı promote etmek garantiyi değiştirebilir. İki veri düğümüyle iki kopyaya senkron yazımı sürdürmek, bir düğüm yokken mümkün değildir.

3. Patroni ile Otomatik Failover Mantığı

Patroni PostgreSQL süreçlerini ve liderliğini yönetir. Kullanılan Patroni/etcd sürümlerini birlikte sabitleyin; mevcut standalone veriyi benimseme veya yeni cluster bootstrap işlemini ayrı geçiş planıyla tasarlayın. Aynı PostgreSQL örneğini hem dağıtımın bağımsız servisi hem Patroni başlatmamalıdır.

  • Her PostgreSQL düğümünde Patroni çalışır.
  • Örnek 2+1 yerleşimde üç gerçek etcd üyesi VPS1, VPS2 ve VPS3’e dağılır; çoğunluk 2/3’tür.
  • Patroni, etcdv3 DCS üzerinden lider kilidini ve cluster durumunu yönetir. DCS üyeliği, peer/client TLS, kimlik doğrulama ve sınırlı key-prefix yetkileri ayrıca kurulur.
  • Proxy, doğru role ait sağlık kontrolüne göre yeni bağlantıları yönlendirir; bağlantı havuzu tek başına lider seçmez.

Yapı kabaca şu şekilde görünür:

  • VPS1: PostgreSQL + Patroni + etcd1.
  • VPS2: PostgreSQL + Patroni + etcd2.
  • VPS3: etcd3; proxy burada tek örnekse proxy arızası hizmeti kesebilir. Uçtan uca HA için proxy ve uygulama katmanını da çoğaltın.

Lider kilidi, aday uygunluğu, gecikme ve timeline birlikte değerlendirilir. DCS’ye erişememe ile DB kaybı aynı olay değildir. Patroni’nin lider kilidi yenilenemediğinde PostgreSQL’i durdurma davranışını ve watchdog/fencing tasarımını sınayın. Synchronous_mode tek başına her zaman iki kopyaya yazım demek değildir; synchronous_mode_strict uygun standby yokken yazıları engelleyebilir. İptal edilen/belirsiz commit’ler ve manuel failover bu sınırları ayrıca etkiler. HAProxy’nin /primary kontrolü yalnız primary ve leader lock birlikte geçerliyken 200 alır; bunu istemci TLS/doğrulama ayarlarıyla yapılandırın.

4. Örnek Patroni Yapılandırma İskeleti

Aşağıdaki YAML mimari yapılandırma parçasıdır; başlatılabilir tam cluster tarifi değildir. etcd üyelik/peer TLS bootstrap’ı, PostgreSQL initdb veya mevcut veri kabul planı, pg_hba/TLS parametreleri, yedek/restore yöntemi, watchdog ve sertifika güven zinciri ayrıca hazırlanır. REPLACE_WITH_* değerleri otomatik genişlemez; sırları kontrollü yapılandırma dağıtımıyla sağlayın ve dosyayı yalnız servis hesabının okuyabileceği şekilde koruyun. YAML anahtarları Patroni 4.1.0 başvurusuna göre gösterilmiştir; seçtiğiniz desteklenen Patroni sürümünün belgeleriyle karşılaştırın.

scope: app-ha
namespace: /service/
name: pg1

restapi:
  listen: 10.0.0.1:8008
  connect_address: pg1.internal.example.com:8008
  certfile: /etc/patroni/tls/server.crt
  keyfile: /etc/patroni/tls/server.key
  authentication:
    username: patroni_api
    password: REPLACE_WITH_API_SECRET

etcd3:
  hosts:
    - etcd1.internal.example.com:2379
    - etcd2.internal.example.com:2379
    - etcd3.internal.example.com:2379
  protocol: https
  cacert: /etc/patroni/tls/etcd-ca.crt
  cert: /etc/patroni/tls/etcd-client.crt
  key: /etc/patroni/tls/etcd-client.key
  username: patroni_dcs
  password: REPLACE_WITH_DCS_SECRET

postgresql:
  listen: 10.0.0.1:5432
  connect_address: pg1.internal.example.com:5432
  data_dir: /var/lib/postgresql/17/patroni
  bin_dir: /usr/lib/postgresql/17/bin
  authentication:
    superuser:
      username: postgres
      password: REPLACE_WITH_ADMIN_SECRET
    replication:
      username: repl
      password: REPLACE_WITH_REPLICATION_SECRET
      sslmode: verify-full
      sslrootcert: /etc/postgresql/tls/ca.crt

pg2’de name, tüm listen/connect_address alanları, node’a özgü sertifika/anahtarlar, veri ve binary yolları doğrulanır; yalnız iki alanı değiştirmek yeterli değildir. DCS üyeleri pg1/pg2/helper üzerinde önceden kurulu ve erişilebilir olmalıdır. etcd v2 anahtarları v3’te görünmez; mevcut DCS’yi yalnız bölüm adını değiştirerek taşıyamazsınız. etcdv3 gRPC gateway’de TLS common-name kimliği DCS kullanıcı yetkilendirmesinin yerine geçmez. REST API’nin TLS doğrulamasını tüm Patroni üyeleri, proxy ve yönetim istemcilerinde yapılandırın; API portunu izinli kaynaklarla sınırlayın, değişiklik uçlarını kimlik doğrulamayla koruyun.

Replikasyon gecikmesini CPU, disk, WAL ve vacuum baskısıyla birlikte değerlendirin. shared_buffers/work_mem ayarları ve WAL optimizasyonları kapasite ölçümüne dayanmalıdır; performans ayarı tek başına HA sağlamaz.

İlgili rehber: VPS üzerinde PostgreSQL performans ayarları.

Uygulama Katmanı: Bağlantıları Nasıl Akıllandırırsınız?

Sadece veritabanı tarafında replikasyon kurmak, uygulamanın bunu doğru kullanacağı anlamına gelmez. HA’nın gerçekten işe yaraması için, uygulamanın veritabanına bağlanma şekli de tasarımın bir parçası olmalı.

MySQL İçin Bağlantı Stratejileri

  • Uygulama için kararlı bir proxy hostname’i kullanın; proxy’lerin kendisi de hata toleranslı olmalıdır.
  • Okuma/yazma ayrımında gecikmiş replica, yazdıktan hemen sonra eski veri döndürebilir. Tutarlılık isteyen okumaları primary’ye veya doğrulanmış uygun replica’ya yönlendirin.
  • VIP yalnız sağlayıcının ağ/ARP, anti-spoof ve IP taşıma yöntemi destekliyorsa kullanılabilir; gerekiyorsa sağlayıcı API’si gerekir. DNS değişikliği cache/TTL ve yeniden bağlantıya bağlıdır.
  • Proxy, DNS veya VIP değişimi açık TCP oturumunu ve yarım işlemi yeni sunucuya taşımaz. Havuz yenileme, yeniden bağlanma ve idempotent işlem tekrarını tasarlayın.

Proxy bağlantı mantığını merkezileştirir; leader seçim/fencing politikasını kendiliğinden oluşturmaz. Doğrudan DB IP’sine giden işler ve yönetim bağlantıları da eski primary’ye yazmayı bırakmalıdır.

PostgreSQL İçin Bağlantı Stratejileri

PgBouncer bağlantı havuzudur; dahili primary seçimi veya failover tespiti yapmaz. HAProxy gibi role-aware bir katmanın arkasına bağlanabilir veya dış otomasyonla hedefi güncellenebilir.

  • HAProxy, Patroni /primary yanıtını ve TLS güvenini kontrol ederek yazılabilir backend’i seçer.
  • Uygulama kararlı endpoint’e bağlanır; proxy katmanı ve DCS ayrı ayrı yedekli tasarlanır.
  • Failover sonrası PgBouncer sunucu bağlantılarını yenileme ve uygulamanın yeniden bağlanma davranışı doğrulanır. Belirsiz commit sonucunda kör tekrar çift işlem oluşturabilir; işlem anahtarı ve uzlaştırma gerekir.

Bu düzen lider değişiminin adres yönetimini azaltır; kesintisiz açık oturum veya tam otomatik iş kurtarma garantisi vermez.

İzleme, Alarm ve Runbook: HA’nın Sigortası

İzleme ve runbook, ilk kurulum kadar gereklidir. Sürüm, ağ, veri hacmi veya saklama politikası değiştiğinde arıza davranışını tekrar değerlendirin; sadece ilk günkü başarılı testlere güvenmeyin.

İzlenmesi Gereken Temel Metrikler

  • MySQL: Replica_IO_Running/Replica_SQL_Running, Last_IO/SQL_Error, tüm applier worker hataları, GTID farkları ve Seconds_Behind_Source sınırları.
  • PostgreSQL: pg_stat_replication state/sync_state ve write/flush/replay LSN; standby receive/replay durumları ve pg_replication_slots retained WAL/slot kullanılabilirliği.
  • WAL/binlog diski, arşiv hataları, backup/restore başarısı ve tutarlılık kontrolleri.
  • DCS quorum/leader lease, fencing, proxy role kontrolü ve uygulama yazma/okuma/yeniden bağlantı sentetikleri.
  • CPU, RAM, disk gecikmesi, ağ kaybı ve bağlantı havuzu kapasitesi.

Bu konuyu somut örneklerle ele aldığımız VPS izleme ve uyarı kurulum rehberi, HA veritabanı mimarinizin üstüne koymanız gereken önemli bir katman.

Runbook: Arıza Anında Kim Ne Yapacak?

Otomatik failover olsa bile, bazı senaryolarda manuel onarım gerekir. Örneğin:

  • Eski primary dönünce ağ ve uygulama erişimi kapalı kalır. MySQL’de GTID ve ayrışan yazılar analiz edilir; yeni primary ile otomatik veri birleştirme yapılmaz. Gerekiyorsa doğrulanmış yeni seed ile replica kurulur.
  • PostgreSQL’de pg_rewind için hedef durdurulmuş olmalı; önceden etkin data checksums veya wal_log_hints, full_page_writes ve gerekli WAL geçmişi gerekir. Eski veriyi koruyun; başarısız rewind hedefi kullanılamaz bırakabilir. Ayarları yeniden standby olacak biçimde doğrulayın; şartlar sağlanmıyorsa yeni base backup kullanın.
  • Binlog/WAL saklama sınırını aşmış replica için yeniden seed, veri hacmi, süre ve bant genişliği planını hazırlayın.
  • DCS, DNS/VIP veya proxy bozulduğunda kimin yazıları durduracağı, kimin fencing/promotion yapacağı ve hangi kanıtlarla trafiğin açılacağı önceden belirli olsun.

Bu soruların yanıtlarını önceden yazılmış bir runbook’ta netleştirmek, felaket anında “şimdi ne yapıyoruz?” paniğini ciddi şekilde azaltır. Felaket kurtarma planı ve runbook hazırlama rehberimiz, bu aşamada iyi bir tamamlayıcıdır.

Test Senaryoları: Replikasyon ve Failover Gerçekten Çalışıyor mu?

Kurulum bittiğinde, “loglarda hata yok” diye rahatlamak yeterli değil. En azından aşağıdaki testleri düzenli aralıklarla yapmanızı öneriyoruz:

1. Replikasyon Tutarlılık Testi

  • İzole test ortamında benzersiz işlem kimlikleriyle veri oluşturun ve commit yanıtlarını kaydedin.
  • Replica’nın doğru GTID/LSN noktasına gelmesini bekledikten sonra veri ve iş değişmezlerini karşılaştırın; değişen iki tabloyu farklı anlarda hashlemek yalancı fark üretebilir.
  • Yedek geri yüklemede şema, rutin, rol/izin ve uygulama sorgularını da kontrol edin.

pt-table-checksum özel yetkiler, kaynak üzerinde checksum yazıları ve statement-based logging davranışı gerektirir; ROW topolojisi, zincir replica ve kullanılan MySQL 8.4 sürümü için uyumluluğu doğrulamadan çalıştırmayın. PostgreSQL pg_checksums, kapatılmış cluster’ın fiziksel sayfa checksum’larını denetler; primary ile replica tablolarının mantıksal olarak eşit olduğunu göstermez.

2. Kontrollü Failover Testi

  • Önce izole ortamda primary kaybı, ağ bölünmesi, DCS çoğunluk kaybı, replica gecikmesi ve dolan disk senaryolarını sınayın.
  • Eski primary’nin yazamadığını ve tek yeni primary olduğunu kanıtlayın; yalnız servis stop testi ağ bölünmesini kapsamaz.
  • Proxy/VIP/DNS, mevcut bağlantılar, yeni bağlantılar ve belirsiz commit tekrarını uygulama üzerinden test edin.
  • Onaylanmış işlem kimlikleriyle gerçek kaybı (RPO) ve başarılı uygulama işlemlerine dönüş süresini (RTO) ölçün; eski primary’yi güvenli biçimde replica olarak geri alın.

İzole testler tamamlandıktan sonra üretim tatbikatını onaylı bakım planı, geri dönüş ve izleme ile yürütün. Düşük trafik tek başına güvenli test koşulu değildir.

VPS, Dedicated ve Colocation İçin Altyapı Seçimi

DCHost üzerinde VPS, dedicated veya colocation değerlendirirken HA tasarımının ihtiyaçlarını seçtiğiniz hizmetin gerçek özellikleriyle eşleştirin. Satın alma veya taşıma öncesinde şu gereksinimleri doğrulayın:

  • Sürekli yazma yükünde ölçülen disk gecikmesi/IOPS ve WAL/binlog için yeterli boş alan.
  • Düğümlerin bağımsız fiziksel host, depolama ve ağ arıza alanlarına yerleştirilebilmesi.
  • İç ağ, firewall ve gerekiyorsa IP taşıma/VIP desteği; yönetim ve fencing erişimi.
  • Off-host yedekler, restore süresi ve destek/işletim sorumluluklarının açık tanımı.

İki düğümlü replikasyon, daha büyük tek sunucu veya yönetilen bir cluster arasında karar verirken RPO/RTO, bütçe ve operasyon becerisini birlikte değerlendirin. Ürün ve hizmet kapsamını doğrulayarak ölçeklendirin.

İlgili rehber: yüksek erişilebilirlik mi güçlü tek sunucu mu.

Özet ve Sonraki Adımlar

Güvenilir HA, tutarlı ilk kopya, doğru replikasyon onayı, yeterli quorum, eski yazıcıyı durduran fencing ve uygulamanın toparlanmasıyla tamamlanır. Bu rehberdeki MySQL 8.4 GTID ve PostgreSQL 17 streaming örneklerini kendi sürüm, veri ve ağ koşullarınızda sınayın; komutların çalışması tek başına erişilebilirlik hedefinin karşılandığını göstermez.

Buradan sonra atabileceğiniz somut adımlar şunlar olabilir:

  • Mevcut veritabanı mimarinizi çıkarıp, RPO/RTO hedeflerinizi netleştirmek
  • Küçük bir ortamda (örneğin 2+1 VPS) MySQL veya PostgreSQL replikasyonunu deneysel olarak kurmak
  • Yedekleme stratejinizi, replikasyon yapınızla çelişmeyecek şekilde güncellemek
  • İzleme ve alarm katmanını, HA ihtiyaçlarınıza göre yeniden tasarlamak

DCHost’ta bir altyapı seçerken veri hacminizi, RPO/RTO hedefinizi, yedek/restore planınızı ve bağımsız arıza alanı gereksiniminizi somutlaştırın. Replikasyon, proxy ve otomatik failover’ı ölçülen ihtiyaç ve test sonuçlarına göre ekleyin.

Resmî Teknik Kaynaklar

Sıkça Sorulan Sorular

Evet. Hatalı silme, migration veya mantıksal bozulma replica’ya da taşınabilir. Off-host yedekler, gerekli binlog/WAL geçmişi ve test edilmiş geri yükleme ile geçmişe dönülebilir. LVM snapshot tek başına veritabanı tutarlılığını garanti etmez; kullanılan motorun yedek koordinasyonuna ihtiyaç vardır. Replikasyon, yedek ve otomatik failover farklı sorunları çözer.

Tek bir VPS içindeki ek süreç veya replica, o VPS’in kaybına karşı bağımsız veri kopyası sağlamaz. İhtiyaç, tolere edilmesi gereken arızaya göre belirlenir. Bu rehberde iki PostgreSQL veri düğümü ve üç gerçek etcd üyesi kullanılır; etcd üyeleri iki DB VPS’i ile yardımcı VPS’e dağılır ve quorum 2/3’tür. Tek proxy hâlâ hata noktasıdır. İki kopyaya senkron yazım şartı varsa bir veri düğümü kaybedildiğinde yazılar durabilir.

Risk gerçektir. Primary’nin onayladığı ancak uygun replica’ya güvenli biçimde ulaşmamış işlemler failover sırasında kaybolabilir. Gecikmenin üst sınırı yoksa kayıp birkaç saniyeyle sınırlı değildir. MySQL yarı senkron onayı relay log flush’ını doğrular, apply’ı değil; timeout asenkrona dönebilir. PostgreSQL’de synchronous_commit ve synchronous_standby_names onay seviyesini belirler. Aday seçimi, fencing ve belirsiz commit’ler de test edilmelidir.

Kararı RTO, veri kaybı toleransı ve işletim kapasitesine göre verin. Otomasyon yanlış arıza tespitiyle gereksiz promotion yapabilir. DCS/controller quorum, aday uygunluğu, eski primary’nin fencing ile yazamaz duruma getirilmesi ve istemci toparlanması birlikte doğrulanmalıdır. Önce izole arıza testleri ve manuel runbook, ardından kontrollü otomasyon uygundur; bazı belirsiz veya ayrışmış veri senaryoları yetkili insan müdahalesi gerektirir.
↑