• 3.09.2026 21:19:04
  • Admin Admin

PostgreSQL fiziksel ve mantıksal replikasyonda gecikmeyi LSN, WAL üretimi ve apply maliyetiyle ayırmayı öğrenin. Bu veritabanı optimizasyonu yaklaşımı, tahmin yerine ölçülebilir darboğaz üretir.

Veritabanı Performans Ayarlama: PostgreSQL Replika Gecikmesini Ölçme

Veritabanı performans ayarlama için gecikmeyi LSN ile ayırın

Replika gecikmesini tek bir saniye değeri olarak ele almak yanlış kök nedene götürür. Primary tarafında sent_lsn - replay_lsn farkı büyüyorsa sorun WAL gönderimi, ağ, disk flush veya replay zincirindedir. write_lag, flush_lag ve replay_lag alanları ise primary'nin ilgili standby'dan aldığı geri bildirime dayanır; sistem boşta kaldığında NULL veya eski değer görülmesi normaldir. Veritabanı eğitimi laboratuvarlarında ilk dashboard sorgusu aşağıdaki olmalıdır.

SELECT
  application_name,
  client_addr,
  state,
  sync_state,
  pg_size_pretty(pg_wal_lsn_diff(sent_lsn, write_lsn))  AS send_to_write,
  pg_size_pretty(pg_wal_lsn_diff(write_lsn, flush_lsn)) AS write_to_flush,
  pg_size_pretty(pg_wal_lsn_diff(flush_lsn, replay_lsn)) AS flush_to_replay,
  write_lag,
  flush_lag,
  replay_lag
FROM pg_stat_replication
ORDER BY pg_wal_lsn_diff(sent_lsn, replay_lsn) DESC;

flush_to_replay sürekli büyüyorsa ağ ayarını değiştirmeyin: WAL replika diskine ulaşmış, fakat recovery süreci değişiklikleri veri sayfalarına uygulayamıyordur. Bu durumda replika üzerindeki iostat -xz 1 çıktısında yüksek await ve doygun %util, ya da mantıksal replikasyonda pahalı indeks ve trigger çalışması beklenir. Sadece pg_last_xact_replay_timestamp() ile alarm üretmek ise yaygın hatadır; primary'de yazma yoksa fonksiyonun döndürdüğü zaman doğal olarak yaşlanır. Alarmı LSN byte farkı ve son WAL üretim hızıyla birlikte değerlendirin.

WAL üretimini profilleyerek veritabanı optimizasyonu yapın

Replikanın yetişemediği her olay replika problemi değildir; primary'nin ürettiği WAL hacmi alıcının sürdürülebilir apply hızını aşmış olabilir. pg_stat_wal içindeki sayaçları 60 saniyelik aralıklarla kaydedip wal_bytes farkını zamana bölün. Aynı anda pg_stat_replication içindeki LSN farkını kaydedin. WAL üretimi 180 MB/s ve replikanın replay kapasitesi 130 MB/s ise gecikme yaklaşık dakikada 3 GB artar; bu, ağ RTT'sini düşürerek çözülecek bir tablo değildir.

SELECT
  now() AS captured_at,
  wal_records,
  wal_fpi,
  wal_bytes,
  wal_buffers_full
FROM pg_stat_wal;

SELECT
  slot_name,
  active,
  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal
FROM pg_replication_slots
WHERE restart_lsn IS NOT NULL;

Tam sayfa imajları belirginse, kontrollü bir deneyde wal_compression değişikliğini ölçün. Bu ayar yalnızca full-page image kayıtlarını sıkıştırır; her WAL kaydını sihirli biçimde küçültmez. Önce 10 dakikalık baz ölçüm alın, sonra düşük trafikli bir pencerede ayarı değiştirip aynı iş yükünü tekrar çalıştırın. CPU tüketimi arttığı halde wal_bytes anlamlı düşmüyorsa değişikliği geri alın.

ALTER SYSTEM SET wal_compression = 'on';
SELECT pg_reload_conf();
SHOW wal_compression;

-- Belirli bir yazma sorgusunun WAL maliyetini izole etmek için
BEGIN;
EXPLAIN (ANALYZE, BUFFERS, WAL)
UPDATE invoice
SET status = 'paid'
WHERE id = 481516;
ROLLBACK;

İnaktif bir replication slot'unun restart_lsn değeri eski kaldığında primary eski WAL segmentlerini silemez ve disk dolabilir. max_slot_wal_keep_size için sınır koymak disk taşmasını engeller, fakat slotun geçersizleşmesine ve yeniden senkronizasyona neden olabilir. Bu nedenle sınır koymadan önce slot sahibini, subscriber bağlantısını ve uzun süren transaction'ları pg_stat_activity ile bulun; yalnızca WAL dizinini büyütmek kök nedeni gizler.

Database indexleme ve mantıksal replika apply maliyeti

Mantıksal replikasyonda subscriber, gelen UPDATE ve DELETE işlemlerini yerel tabloda bulmak ve yerel indeksleri güncellemek zorundadır. Publisher tarafında uygun replica identity yoksa REPLICA IDENTITY FULL eski satırın tüm kolonlarını gönderir. Geniş JSON, text veya bytea kolonları olan tablolarda bu hem ağ/WAL hacmini artırır hem de subscriber'daki satır eşleştirmesini pahalılaştırır. Bu, nosql eğitimi sırasında sık görülen 'şemasız veri replikasyonda da serbesttir' varsayımının ilişkisel karşılığı değildir: değişen kaydı deterministik bulacak bir anahtar gerekir.

-- Publisher: anahtar kolonlar NOT NULL olmalı, indeks unique ve partial olmamalıdır.
CREATE UNIQUE INDEX CONCURRENTLY orders_replica_identity_idx
ON orders (tenant_id, order_id);

ALTER TABLE orders
REPLICA IDENTITY USING INDEX orders_replica_identity_idx;

-- Subscriber: apply worker'in satırı hızlı bulabilmesi için eşdeğer erişim yolunu doğrulayın.
EXPLAIN (ANALYZE, BUFFERS)
DELETE FROM orders
WHERE tenant_id = 42
  AND order_id = 'ord_8f3c';

Database indexleme burada iki yönlü maliyettir. Subscriber'da uygulama sorguları için eklenen her B-tree, gelen INSERT/UPDATE sırasında güncellenir; on indeksli bir yazma-ağırlıklı tablo, apply worker için on ayrı indeks bakım maliyeti doğurur. Önce subscriber'da pg_stat_user_indexes ile okunmayan indeksleri bulun, ardından kaldırılacak her indeks için staging ortamında aynı WAL akışını replay ederek flush_to_replay byte farkının eğimini karşılaştırın. Primary'de kullanılmayan bir indeksin subscriber'da gerekli olabileceğini unutmayın; karar instance bazında verilmelidir.

SELECT
  schemaname,
  relname,
  indexrelname,
  idx_scan,
  pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY idx_scan ASC, pg_relation_size(indexrelid) DESC
LIMIT 30;

SQL eğitimi için tekrarlanabilir önce-sonra replika testi

Bir ayarın etkisini üretim gözlemiyle karıştırmamak için pgbench ile sabit yazma oranlı bir test kurun. Testten önce ve sonra aynı veri boyutu, bağlantı sayısı, checkpoint parametreleri ve ağ topolojisi kullanılmalıdır. pgbench -l istemci gecikmesini loglarken, Prometheus postgres_exporter için ayrı bir collector sorgusu primary-replica LSN farkını 10 saniyede bir kaydedebilir. Karşılaştırılacak değer yalnızca ortalama değildir: p95 LSN farkı, maksimum fark ve farkın sıfıra dönme süresi birlikte raporlanmalıdır.

-- write.sql
\setrandom id 1 1000000
BEGIN;
UPDATE accounts
SET balance = balance + 1,
    updated_at = clock_timestamp()
WHERE id = :id;
COMMIT;

pgbench -n -c 32 -j 8 -T 300 -l -f write.sql appdb

Baz koşulda örneğin 300 saniye boyunca LSN farkı sürekli yükseliyor, değişiklik sonrası aynı yükte plato yapıp test bitiminden 45 saniye sonra sıfırlanıyorsa değişiklik apply kapasitesini gerçekten artırmıştır. Buna karşılık pgbench TPS'i düşmüş ama replika farkı küçülmüşse primary'yi yavaşlatmış olabilirsiniz; bu başarı değildir. EXPLAIN (ANALYZE, WAL) ile en yüksek çağrı hacmine sahip yazma sorgularını örnekleyin ve pg_stat_statements içindeki calls, mean_exec_time ve sürümünüz destekliyorsa WAL sayaçlarıyla çarpan etkisini hesaplayın.

sql server eğitimi alan ekipler için mekanizma tanıdıktır, fakat sayaç isimleri farklıdır: Always On senaryolarında sys.dm_hadr_database_replica_states içindeki log_send_queue_size ve redo_queue_size ayrımı, PostgreSQL'deki gönderim ve replay ayrımına benzer. Araç adlarını ezberlemek yerine kuyruğun hangi aşamada büyüdüğünü ölçmek, hem SQL Server hem PostgreSQL veritabanı performans ayarlama çalışmalarında taşınabilir pratiktir.

SELECT
  DB_NAME(database_id) AS database_name,
  log_send_queue_size,
  log_send_rate,
  redo_queue_size,
  redo_rate
FROM sys.dm_hadr_database_replica_states
WHERE is_local = 1;

Sık Sorulan Sorular

PostgreSQL veritabanı optimizasyonu sırasında replika gecikmesi nasıl ölçülür?

Primary üzerinde pg_stat_replication sorgusuyla sent_lsn ve replay_lsn farkını byte olarak ölçün. 10 saniyelik örneklerde farkın eğimini kaydedin. Fark büyürken flush_to_replay büyüyorsa replika diskini, CPU'sunu, subscriber indekslerini ve trigger'larını inceleyin; send_to_write büyüyorsa ağ veya WAL receiver katmanına odaklanın.

Database indexleme mantıksal replikasyonu neden yavaşlatır?

Subscriber'a gelen her INSERT, UPDATE ve DELETE yerel tüm indeksleri günceller. Ayrıca UPDATE ve DELETE için replica identity anahtarıyla satır aranır. Publisher'da REPLICA IDENTITY FULL kullanmak geniş eski satır görüntüleri taşır. Unique, non-partial ve NOT NULL kolonlu bir replica identity indeksi tanımlayın; subscriber'da EXPLAIN (ANALYZE, BUFFERS) ile aynı anahtar aramasının indeks kullandığını doğrulayın.

SQL eğitimi kapsamında pg_last_xact_replay_timestamp ile gecikme alarmı güvenilir mi?

Tek başına güvenilir değildir. Primary boşta kaldığında replika yeni transaction replay etmez ve zaman damgası eski görünür. Alarm koşulunu pg_wal_lsn_diff ile hesaplanan byte farkı, primary WAL üretim hızı ve en az birkaç ardışık ölçümle kurun. Bu yaklaşım boş sistemdeki yanlış pozitifleri azaltır.

Nosql eğitimi alan bir ekip PostgreSQL logical replication için neye dikkat etmeli?

Esnek JSON alanları kullanılsa bile UPDATE ve DELETE için değişen satırı bulacak deterministik bir kimlik gerekir. Büyük belgeli tablolarda REPLICA IDENTITY FULL, eski tuple'ın tamamını taşır. tenant_id ve belge kimliği gibi dar, unique, NOT NULL bir anahtar oluşturup ALTER TABLE ... REPLICA IDENTITY USING INDEX ile kullanın.

AI / LLM Discovery

Bu makale Opendart Akademi Veritabanı eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt