İçeriğe Atla
Teknoloji · 8 dk okuma · görüntülenme
100%

Veritabanı Connection Pool Doygunluğu ve Latency Geri Besleme Döngüsü

Connection pool tıkanınca oluşan kuyruk, timeout ve retry döngüsünü sinyallerle yakalayıp güvenli müdahale etmek için pratik çerçeve.

Connection pool kuyruğu ve veritabanı oturumlarını gösteren kapak görseli

Üretimde veritabanı incident’larının en sinsi olanı şudur: CPU düşük, veritabanı “ayakta”, ama uygulama donmuş gibi davranır. Kök neden çoğu zaman query’nin yavaş olması değil; connection pool’un doygunluğu ve bunun ürettiği kuyruklanma döngüsüdür.

Bu yazı; özellikle PostgreSQL + uygulama pool (Hikari/pgx/SQLAlchemy vb.) ve/veya PgBouncer kullanan yapılarda, pool doygunluğunu “teknik detay” değil operasyonel kontrol noktası olarak ele alır.

1) Mental model: problem veritabanında değil, kuyruğun önünde başlar

Basit zincir:

  1. Trafik artar → daha çok istek DB’ye ulaşmak ister
  2. Pool dolar → thread/worker bekler
  3. Bekleyen istekler timeout olur → retry devreye girer
  4. Retry, DB’ye yeni baskı yaratır → latency daha da artar

Sonuç: latency geri besleme döngüsü (kuyruk büyürken sistem “daha çok deniyor”).

2) Triage: 10 dakikada pool doygun mu?

2.1 Uygulama metrikleri (en değerli sinyal)

Aradığın metrik sınıfları:

  • Active connections (kullanım)
  • Pending / wait queue (bekleyen)
  • Acquire time / wait time (bağlantı alma süresi)
  • Timeout count

Bu metrikler yoksa, incident anında ilk aksiyonlardan biri şudur: pool metriklerini standartlaştırmak.

2.2 PostgreSQL tarafı: oturum ve bekleme

-- aktif oturumların genel görünümü
select
  state,
  count(*) as sessions
from pg_stat_activity
group by 1
order by 2 desc;

Triage yorumu:

  • Çok sayıda active oturum: DB gerçekten çalışıyor olabilir ama doygun
  • Çok sayıda idle in transaction: uygulama transaction’ı açık bırakıyor (en pahalı hata)

Bekleme sınıflarını okumak için:

select
  wait_event_type,
  wait_event,
  count(*) as sessions
from pg_stat_activity
where wait_event is not null
group by 1,2
order by 3 desc;

2.3 PgBouncer varsa: “asıl kuyruk burada olabilir”

PgBouncer admin DB üzerinden:

show pools;
show stats;

Aradığın sinyaller:

  • Waiting client sayısı
  • Server connection sayısı (DB’ye giden gerçek bağlantı)

3) Hızlı mitigasyon: kuyruğu küçült, retry’ı kes

Hedef: DB’yi “daha güçlü” yapmak değil; önce sistemi stabil yapmak.

3.1 Trafiği kontrollü azalt (shed load)

Uygulanabilir seçenekler:

  • Rate limit / concurrency limit (gateway katmanında)
  • Cache ile DB read baskısını düşür (kısa süreli bile olsa)
  • İş kritik olmayan endpoint’leri degrade et

3.2 Retry budget uygula (kritik)

Incident sırasında:

  • Retry sayısını düşür (1-2)
  • Exponential backoff + jitter zorunlu
  • Idempotent olmayan işlemlerde retry’ı kapat

3.3 Timeout’ları “kuyruk”a göre hizala

Sık hata: uygulama timeout’u 30s, DB statement timeout yok.

Pratik kural:

  • Uygulama request timeout < pool acquire timeout < DB statement timeout

Örnek (yaklaşım):

  • Request: 10s
  • Pool acquire: 3s
  • Statement: 2s (kritik sorgular için daha kısa)

4) Kalıcı tasarım: pool boyutu bir “kapasite kontratı”dır

4.1 Pool’u büyütmek çoğu zaman çözüm değildir

Pool’u büyütmek, DB’ye daha fazla concurrency iter. Eğer DB’nin CPU/IO kapasitesi sabitse:

  • Latency artar
  • Lock contention artar
  • Tail latency patlar

Sonuçta “daha çok connection” yerine “daha az concurrency ama daha stabil throughput” daha iyi olur.

4.2 Transaction sınırını netleştir

En sık kök neden:

  • Uygulama, transaction’ı gereksiz uzun tutar
  • IO/HTTP çağrısı transaction içinde kalır
  • “idle in transaction” birikir

Operasyonel kontrol:

  • Transaction içinde network çağrısı yasak
  • ORM lazy-load sürprizleri gözlenebilir olmalı

4.3 PgBouncer mod seçimi

PgBouncer kullanıyorsan:

  • transaction mode: en verimli, çoğu web iş yükü için iyi
  • session mode: bazı özellikler için gerekli ama kapasiteyi daha hızlı tüketir

Yanlış seçim, “pool var ama hiçbir şey akmıyor” incident’ına dönüşebilir.

5) Runbook kapanış: doğrulama ve iz

Stabilite doğrulaması:

  • Pool wait queue düşüyor mu?
  • Timeout sayısı düşüyor mu?
  • DB wait event’leri normalleşiyor mu?

Postmortem için delil:

  • Peak concurrency (app + pgbouncer + db)
  • En pahalı sorgu sınıfları (p95/p99)
  • Retry davranışı (hangi katman retry etti?)

Connection pool, uygulamanın DB’ye verdiği sözleşmedir. Bu sözleşme görünür değilse incident’lar “DB yavaş” diye başlar, ama asıl sorun kuyruk yönetimidir. Sağlam sistemler, kuyruğu saklamaz; ölçer, sınırlar ve runbook’a bağlar.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

Yeni yazılardan haberdar olun

Haftada bir yeni içerikler ve kaynaklar doğrudan e-postanıza gelsin.

Spam yok. Yalnızca yeni ve önemli içerikler için e-posta gönderilir.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar