Buyukweb
PgBouncer ile PostgreSQL Bağlantı Havuzu: Kurulum ve Yapılandırma

PgBouncer ile PostgreSQL Bağlantı Havuzu: Kurulum ve Yapılandırma

PgBouncer 1.21+ kurulumu, session/transaction/statement pool modu karşılaştırması, pgbouncer.ini yapılandırması, prepared statement çakışması ve SHOW STATS/POOLS izleme — Buyukweb VDS perspektifinden pratik rehber.

Büyükweb Editör EkibiHosting, Sunucu ve Sistem Yönetimi Editörü12 dakika okuma

PgBouncer ile PostgreSQL Bağlantı Havuzu: Kurulum, Yapılandırma ve İzleme

Uygulamanız 200 eşzamanlı istek altında "FATAL: remaining connection slots are reserved" hatası veriyor ve PostgreSQL'in max_connections = 100 sınırını çoktan doldurmuşsunuz. Her bağlantı için yaklaşık 5-10 MB bellek tüketiliyor; 200 bağlantı = 1-2 GB sadece bağlantı overhead'i. Uygulama yavaşlamıyor, doğrudan çöküyor.

Bu senaryonun çözümü PgBouncer — PostgreSQL önüne oturan hafif bir bağlantı havuzu yöneticisi. Bu rehberde PgBouncer 1.21+ kurulumunu, üç pool modunu, kritik pgbouncer.ini parametrelerini, transaction mode'da prepared statement çakışmasını ve izleme sorgularını Buyukweb VDS perspektifinden ele alıyoruz.

Buyukweb perspektifi: cPanel paylaşımlı hosting paketlerimizde veritabanı motoru MariaDB 10.6 LTS'dir; PostgreSQL standart olarak gelmez. Eğer PostgreSQL kullanmak istiyorsanız — özellikle Node.js, Django veya Rails gibi PostgreSQL-ağırlıklı bir stack kuruyorsanız — Buyukweb VDS (₺250/ay başlangıç) üzerinde apt install postgresql-15 veya dnf install postgresql15 ile kendiniz kurarsınız; PgBouncer da ayrı pakettir.

Tercih etmeyin: Tek bir uygulama ve 50 eşzamanlı kullanıcıdan az trafiğiniz varsa PgBouncer gereksiz karmaşıklık ekler. PostgreSQL'in varsayılan max_connections = 100 değeri bu yük için yeterlidir. PgBouncer ihtiyacı şu durumlarda ortaya çıkar: 200+ eşzamanlı bağlantı, çok sayıda microservice'in aynı PostgreSQL'e bağlandığı mimari veya serverless/Lambda tipi scale-to-zero uygulamalar.

PostgreSQL'in "Too Many Connections" Sorunu

PostgreSQL her bağlantı için ayrı bir backend process başlatır. Bu process, bağlantı boşta bile RAM ve process tablosunda yer tutar.

Bağlantı havuzu olmadan:
100 uygulama worker  →  100 PostgreSQL backend process
200 uygulama worker  →  "FATAL: too many connections" ❌

PgBouncer ile:
200 uygulama worker  →  PgBouncer  →  20 PostgreSQL backend process ✓

Neden max_connections = 500 yapmak çözüm değildir? Her bağlantı için shared memory ve process overhead artar; PostgreSQL için önerilen değer 100-200 arasındadır. 20-50 gerçek backend bağlantısıyla 500 uygulama worker'ına hizmet etmek PgBouncer'ın tam olarak yaptığı şeydir.

PgBouncer Nedir ve Üç Pool Modu

PgBouncer, uygulama bağlantılarını PostgreSQL bağlantılarından ayıran bir proxy katmanıdır. Varsayılan portu 6432'dir; PostgreSQL'in önüne geçer.

Pool Modu Karşılaştırması

Özellik Session Pooling Transaction Pooling Statement Pooling
Bağlantı ne zaman serbest bırakılır Uygulama bağlantısı kapanınca Transaction bitince Her SQL ifadesi sonrası
Performans kazancı Düşük Yüksek Çok yüksek (ama kısıtlı)
SET / RESET desteği Evet Hayır Hayır
Prepared statement desteği Evet Protokol seviyesinde hayır* Hayır
LISTEN / NOTIFY desteği Evet Hayır Hayır
Advisory lock desteği Evet Hayır Hayır
Kullanım senaryosu SET kullanan legacy uygulama Çoğu modern web uygulaması Nadiren; basit single-statement

* Transaction mode'da prepared statement protokolü çakışması ayrı başlıkta ele alınmaktadır.

Session pooling bağlantıyı oturum boyunca tutar — bağlantı overhead'ini ortadan kaldırır ama aynı anda açık uygulama bağlantısı kadar PostgreSQL bağlantısı gerekir. Yoğun trafik için yetersiz.

Transaction pooling PostgreSQL bağlantısını yalnızca transaction süresince kullanır, biter bırakır. En çok kullanılan mod budur — 200 uygulama bağlantısı için 20 PostgreSQL bağlantısı yeterli olabilir.

Statement pooling her SQL ifadesini ayrı bir PostgreSQL bağlantısıyla çalıştırır. Multi-statement transaction desteklemediğinden üretimde nadiren kullanılır.

Kurulum: Ubuntu 22.04 / 24.04 (Buyukweb VDS)

Buyukweb VDS'inde Ubuntu kullananlar için:

sudo apt update
sudo apt install pgbouncer -y

# Versiyon doğrula — 1.18+ iyi, 1.21+ SCRAM-SHA-256 tam destek
pgbouncer --version

# PostgreSQL 15 de kurulacaksa (henüz kurulmamışsa)
sudo apt install postgresql-15 -y

Kurulum: AlmaLinux 9 / RHEL 9 (Buyukweb VDS)

# PostgreSQL PGDG deposu
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf -qy module disable postgresql

# PostgreSQL 15 + PgBouncer
sudo dnf install -y postgresql15-server pgbouncer

# PostgreSQL ilk kurulum
sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
sudo systemctl enable --now postgresql-15

pgbouncer.ini Yapılandırması

Ana yapılandırma dosyası /etc/pgbouncer/pgbouncer.ini'dir. Ubuntu'da paket yükleme sonrası otomatik oluşur; AlmaLinux'ta /etc/pgbouncer/pgbouncer.ini el ile oluşturulabilir.

[databases]
; Uygulama veritabanı tanımları
; Format: takma_ad = host=GERÇEK_HOST port=5432 dbname=GERÇEK_DB
uygulama_db  = host=127.0.0.1 port=5432 dbname=uygulama_prod
analitik_db  = host=127.0.0.1 port=5432 dbname=analitik_prod

; Wildcard — tanımsız her DB adını olduğu gibi ilet
; * = host=127.0.0.1 port=5432

[pgbouncer]
; --- Bağlantı ---
listen_addr     = 127.0.0.1   ; Sadece yerel erişim (uygulama aynı sunucudaysa)
listen_port     = 6432

; --- Kimlik doğrulama ---
auth_type       = scram-sha-256   ; PgBouncer 1.21+ önerilen; eski sürümde md5
auth_file       = /etc/pgbouncer/userlist.txt

; --- Pool modu ---
pool_mode       = transaction     ; Çoğu modern uygulama için önerilen

; --- Bağlantı limitleri ---
max_client_conn  = 500    ; Uygulamalardan gelecek maksimum bağlantı
default_pool_size = 20    ; Her DB/kullanıcı çifti için PostgreSQL bağlantısı
max_db_connections = 80   ; Tüm DB'ler için toplam PostgreSQL bağlantısı
min_pool_size    = 5      ; Boşta tutulacak minimum bağlantı
reserve_pool_size = 5     ; Yoğun anlık ek kapasite

; --- Zaman aşımı (saniye) ---
server_idle_timeout   = 600   ; Boşta PostgreSQL bağlantısını kapat
client_idle_timeout   = 0     ; Uygulama zaman aşımı (0 = devre dışı)
server_connect_timeout = 15   ; PostgreSQL'e bağlanma zaman aşımı
reserve_pool_timeout   = 5    ; Normal pool dolduğunda reserve_pool_size devreye giriş süresi

; --- Transaction mode ek ayarları ---
server_reset_query =           ; Transaction mode'da boş bırakın (session mode için: DISCARD ALL)
ignore_startup_parameters = extra_float_digits,options   ; Bazı istemci kütüphaneleri gönderir

; --- Sunucu durumu kontrolü ---
server_check_delay = 30
server_check_query = select 1

; --- Admin / izleme ---
admin_users  = pgbouncer_admin
stats_users  = pgbouncer_stats

; --- Log ---
log_connections    = 1
log_disconnections = 1
log_pooler_errors  = 1
stats_period       = 60

; --- Sistem dosyaları ---
pidfile  = /var/run/pgbouncer/pgbouncer.pid
logfile  = /var/log/pgbouncer/pgbouncer.log

Önemli Parametre Özeti

Parametre Örnek Değer Açıklama
max_client_conn 500 Uygulama katmanından maksimum bağlantı
default_pool_size 20 DB/kullanıcı başına PostgreSQL bağlantısı
max_db_connections 80 Tüm pool'ların toplam PG bağlantısı (max_connections - 10 yapın)
min_pool_size 5 Boşta tutulacak minimum backend
reserve_pool_size 5 Aşım anında acil kapasite
reserve_pool_timeout 5 Acil kapasiteye geçiş süresi (sn)
server_idle_timeout 600 Boşta backend'i kapat (sn)
pool_mode transaction session / transaction / statement
auth_type scram-sha-256 md5 (eski) veya scram-sha-256 (PgBouncer 1.21+)

userlist.txt ve Kimlik Doğrulama

PgBouncer kullanıcıları PostgreSQL üzerinden doğrulayabilir veya kendi userlist.txt dosyasından okuyabilir. İkinci yöntem daha sık kullanılır.

SCRAM-SHA-256 ile (PgBouncer 1.21+, Önerilen)

# PostgreSQL'de kullanıcı parolasının hash'ini çekme
sudo -u postgres psql -c "SELECT usename, passwd FROM pg_shadow WHERE usename = 'uygulama_user';"
# Çıktıdaki 'SCRAM-SHA-256$...' satırını kopyalayın
; /etc/pgbouncer/userlist.txt — SCRAM-SHA-256 format
"uygulama_user" "SCRAM-SHA-256$4096:...<pg_shadow çıktısı>..."
"pgbouncer_admin" "SCRAM-SHA-256$4096:...<hash>..."

MD5 ile (PgBouncer < 1.21 veya eski kurulumlar)

# MD5 hash: "md5" + md5(parola + kullanici_adi)
echo -n "SİFRE_BURAYAuygulama_user" | md5sum
# Çıktı: abc123def456... → "md5abc123def456..."
; /etc/pgbouncer/userlist.txt — MD5 format
"uygulama_user"    "md5abc123def456789012345678901234ab"
"pgbouncer_admin"  "md5def456abc789012345678901234abcd"
# Dosya izinleri — sadece postgres kullanıcısı okuyabilmeli
sudo chown postgres:postgres /etc/pgbouncer/userlist.txt
sudo chmod 640 /etc/pgbouncer/userlist.txt

Servis Başlatma ve Yönetim

# Yapılandırma söz dizimi doğrulama (başlatmadan önce)
pgbouncer -d /etc/pgbouncer/pgbouncer.ini --check-config

# Servisi başlat ve otomatik başlatma
sudo systemctl start pgbouncer
sudo systemctl enable pgbouncer

# Durum kontrol
sudo systemctl status pgbouncer

# Yapılandırmayı yeniden yükle (servis durmadan — bağlantıları kesmez)
sudo systemctl reload pgbouncer

# Veya HUP sinyali
kill -HUP $(cat /var/run/pgbouncer/pgbouncer.pid)

Transaction Mode ve Prepared Statement Çakışması

Bu, production'da en sık karşılaşılan sorundur. Transaction pooling modunda her transaction farklı bir backend bağlantısı alabilir. Eğer uygulamanız protokol seviyesinde (binary protocol) prepared statement kullanıyorsa — PREPARE my_stmt AS SELECT...; — ve bağlantı transaction sonrası farklı backend'e verilirse prepared statement bulunamaz, hata alırsınız.

Etkilenen senaryolar:

  • psycopg2 / psycopg3 cursor.execute ile prepared statement kullanımı
  • node-postgres (pg) ile prepare adlı sorgular
  • JDBC ürünlerinde prepareStatement + useServerPrepStmts=true

Çözüm 1 — Prepared statement'ı devre dışı bırakın (önerilen):

; pgbouncer.ini — transaction mode'da prepared statement devre dışı
[pgbouncer]
pool_mode = transaction
; Aşağıdaki parametre PgBouncer 1.21+ ile protokol seviyesinde önbelleği kapatır
; (istemci kütüphanesine göre ek ayar gerekebilir — aşağıya bakın)

Çözüm 2 — Uygulama tarafında prepared statement kullanmayı kapatın:

# Python psycopg3 — prepared statement devre dışı
import psycopg

conn = psycopg.connect(
    "host=127.0.0.1 port=6432 dbname=uygulama_db user=uygulama_user password=SİFRE",
    prepare_threshold=None   # Prepared statement kullanma
)

Çözüm 3 — Session pooling'e geçin (prepared statement gerekiyorsa ve transaction mode çalışmıyorsa):

Session pooling ile prepared statement çakışması olmaz; ancak pool verimliliği düşer.

Uygulama Bağlantısı: Doğru Connection String

Uygulama PgBouncer portuna (6432) bağlanır, PostgreSQL portuna (5432) değil.

Python — psycopg2 / psycopg3

import psycopg2

# Transaction mode için CONN_MAX_AGE = 0 (Django) veya kısa yaşam süresi
conn = psycopg2.connect(
    host="127.0.0.1",
    port=6432,          # PgBouncer portu!
    dbname="uygulama_db",
    user="uygulama_user",
    password="SİFRE",
    sslmode="prefer"
)

Django settings.py (transaction mode için CONN_MAX_AGE = 0):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME':     'uygulama_db',
        'USER':     'uygulama_user',
        'PASSWORD': 'SİFRE',
        'HOST':     '127.0.0.1',
        'PORT':     '6432',       # PgBouncer
        'CONN_MAX_AGE': 0,        # Transaction mode: bağlantıyı işlem sonrası bırak
    }
}

Node.js — pg kütüphanesi

const { Pool } = require('pg');

const pool = new Pool({
  host:     '127.0.0.1',
  port:     6432,          // PgBouncer portu
  database: 'uygulama_db',
  user:     'uygulama_user',
  password: 'SİFRE',
  max:      10,            // Uygulama tarafı havuz — PgBouncer'a paralel 10 bağlantı
  idleTimeoutMillis: 30000,
  // Transaction mode + node-postgres: prepared statement kullanmayın
  // types kütüphanesi ile pg-types kapatılabilir
});

JDBC (Java / Spring Boot)

jdbc:postgresql://127.0.0.1:6432/uygulama_db?prepareThreshold=0&sslmode=prefer

prepareThreshold=0 server-side prepared statement'ı devre dışı bırakır — transaction pooling ile uyumlu.

İzleme: SHOW STATS, SHOW POOLS

PgBouncer, 6432 portunda pgbouncer adında bir sahte veritabanı sunar. Buraya bağlanarak anlık durum sorgulanır.

# Admin konsoluna bağlan
psql -h 127.0.0.1 -p 6432 -U pgbouncer_admin pgbouncer
-- Genel istatistikler: toplam istek, toplam bekleme, saniyedeki sorgu
SHOW STATS;

-- Pool durumu: aktif/boşta/bekleme bağlantı sayıları
SHOW POOLS;

-- Sunucu bağlantıları (PostgreSQL'e açık)
SHOW SERVERS;

-- İstemci bağlantıları (uygulamadan gelen)
SHOW CLIENTS;

-- Veritabanı başına limit ve anlık durum
SHOW DATABASES;

-- Yapılandırma parametrelerini gör
SHOW CONFIG;

-- Anlık ayar değişikliği (reload etmeden)
SET server_idle_timeout = 300;

-- Yapılandırmayı yeniden yükle (userlist.txt dahil)
RELOAD;

-- Belirli veritabanını geçici durdur / devam ettir
PAUSE uygulama_db;
RESUME uygulama_db;

İzleme Komutu Özeti

Komut Ne Gösterir
SHOW STATS; DB başına toplam istek, sorgu süresi, beklemeler
SHOW POOLS; Pool başına cl_active, cl_waiting, sv_active, sv_idle sayıları
SHOW SERVERS; PostgreSQL backend bağlantıları (state, connect_time)
SHOW CLIENTS; Uygulama bağlantıları (state, wait_time)
SHOW DATABASES; DB tanımları, pool_size, max_connections, anlık durum
SHOW CONFIG; Tüm pgbouncer.ini parametreleri ve değerleri

SHOW POOLS'ta cl_waiting sürekli artıyorsa pool dolu — default_pool_size artırın. sv_idle çok yüksekse min_pool_size düşürülebilir.

Prometheus ile İzleme

pgbouncer_exporter PgBouncer istatistiklerini Prometheus formatına çevirir; 9127 portunda metrikleri sunar. Prometheus + Grafana kuruluysa pgbouncer_* metrikleriyle pool boyutu ve bekleme süresi görselleştirilebilir.

HAProxy + Patroni ile Yüksek Erişilebilirlik (Kısa Bakış)

PgBouncer tek başına yük dengeleme yapmaz. Patroni ile primary/replica cluster kurduysanız PgBouncer önüne HAProxy koyun:

Uygulama → PgBouncer (6432) → HAProxy (5000) → Patroni primary (:5432)

HAProxy, Patroni REST API (/primary, /replica) üzerinden sağlık kontrolü yapar; failover anında PgBouncer yeni primary'ye yönlendirilir. Bu kurulum Buyukweb VDS üzerinde çalışır; birden fazla VDS ve ek yönetim karmaşıklığı gerektirir — tek node için gerekli değildir.

Sıkça Sorulan Sorular

Hangi pool modunu seçmeliyim — session mi, transaction mı?

Çoğu modern web framework'ü (Django, Rails, Node.js Express, FastAPI) transaction modunu destekler. SET komutları, advisory lock veya LISTEN/NOTIFY kullanmıyorsanız transaction pooling seçin — en yüksek bağlantı verimliliğini sağlar. Legacy bir uygulama veya SET bağımlı kütüphane varsa session pooling tercih edin.

Transaction mode'da ORM hazır mı?

SQLAlchemy (pool_pre_ping=True, autocommit=False) ve Django (CONN_MAX_AGE=0) transaction mode ile uyumlu çalışır. ActiveRecord (Rails) de uyumludur. JDBC için prepareThreshold=0 eklemeniz yeterlidir.

PgBouncer kendisi bir SPOF (single point of failure) değil mi?

Evet — tek PgBouncer instance'ı varsa çökünce uygulama PostgreSQL'e ulaşamaz. Çözüm: aynı sunucuda iki PgBouncer instance (farklı port) + systemd servis izleme, ya da birden fazla VDS'de HAProxy + PgBouncer. Küçük ölçekli kurulumlar için systemd ile Restart=always yeterli.

max_client_conn ile default_pool_size arasındaki ilişki nedir?

max_client_conn uygulama katmanından PgBouncer'a gelen maksimum bağlantıdır — bu sayı PostgreSQL bağlantısından bağımsız büyük olabilir. default_pool_size ise gerçek PostgreSQL backend bağlantısıdır. Örnek: max_client_conn=500, default_pool_size=20 — 500 uygulama bağlantısı, 20 PostgreSQL bağlantısıyla servis edilir.

PostgreSQL max_connections ile max_db_connections nasıl dengelenir?

PostgreSQL max_connections değeri sunucu genelinde toplam backend limiti. PgBouncer max_db_connections bu sınırın PgBouncer'a ayrılan payı. Formül: max_db_connections = max_connections - süper kullanıcı_bağlantıları - 5. Örnek: PostgreSQL max_connections=100 ise PgBouncer max_db_connections=90 mantıklı.

PgBouncer SSL desteği var mı?

Evet. Hem istemci (uygulama → PgBouncer) hem sunucu (PgBouncer → PostgreSQL) tarafında TLS yapılandırılabilir:

; pgbouncer.ini
client_tls_sslmode = require
client_tls_key_file  = /etc/pgbouncer/pgbouncer.key
client_tls_cert_file = /etc/pgbouncer/pgbouncer.crt

server_tls_sslmode = require

PgBouncer ile pgpool-II arasındaki fark nedir?

PgBouncer yalnızca connection pooling yapar — hafif, hızlı, basit. pgpool-II connection pooling yanı sıra load balancing, replication ve query cache özelliklerine sahip; daha ağır ve yapılandırması karmaşık. Yalnızca bağlantı sayısını yönetmek istiyorsanız PgBouncer, load balancing + replication birlikte gerekiyorsa pgpool-II veya HAProxy + PgBouncer kombinasyonu düşünülebilir.

Sonuç

PostgreSQL "too many connections" hatası alan bir uygulamada PgBouncer'ı devreye almak genellikle birkaç saatlik iştir: kurulum, pgbouncer.ini yapılandırması, userlist.txt oluşturma ve uygulama connection string'ini 5432'den 6432'ye taşıma. Transaction mode seçtiyseniz hazır prepared statement kullandığınızı önceden doğrulayın — bu tek tuzak noktasıdır.

Buyukweb VDS (₺250/ay başlangıç) üzerinde PostgreSQL 15 + PgBouncer 1.21 kurulumu tamamen sizin kontrolünüzde. Root yetkisi vardır, pgbouncer.ini dilediğiniz gibi ayarlanır; Veeam altyapısıyla günlük otomatik sunucu yedeklemesi de Buyukweb tarafından yapılmaktadır.

Teknik destek için: 0850 302 60 70 veya iletişim sayfamız.


İlgili Büyükweb Hizmetleri

Veritabanı odaklı uygulamalar için altyapı seçeneklerimiz:

  • VDS Sunucu — root yetkili, PostgreSQL + PgBouncer serbestçe kurulabilir
  • E5 v4 VDS — NVMe SSD, yüksek IOPS, PostgreSQL yoğun iş yükleri için
  • Fiziksel Dedicated — Tam kontrol, büyük ölçekli veritabanı iş yükleri
  • cPanel Web Hosting — MariaDB 10.6 LTS, küçük ve orta ölçekli uygulamalar

Sorularınız için 0850 302 60 70 numaralı destek hattımıza veya iletişim sayfamıza yazabilirsiniz.

Veritabanı Yönetimi İlgili Hizmetlerimiz

Bu yazıda anlatılan teknik konuyu profesyonel altyapıyla deneyimleyin

Etiketler:

#postgresql#pgbouncer#ağ yönetimi#veritabanı#database#veri yönetimi

Bu yazıyı paylaş