PostgreSQL "too many clients already" Hatası: Nedeni, Acil Müdahale ve Kalıcı Çözüm
FATAL: sorry, too many clients already hatasının üç nedeni, nedeni ayırt eden tek sorgu ve max_connections ile PgBouncer üzerinden kalıcı çözümü.
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
Uygulama bir anda tüm bağlantıları kaybediyor; loglarda şu satır tekrar ediyor:
FATAL: sorry, too many clients alreadyBu, veritabanının çöktüğü anlamına gelmez. PostgreSQL'e gelen bağlantı sayısı max_connections sınırına ulaşmıştır ve yeni istemciler reddedilir. Kritik ayrıntı şu: hata, mevcut bağlantıların çok olmasından değil, çoğunun boşta durmasından kaynaklanır. Üretimde tipik tablo, 100 bağlantının 80'inin idle olmasıdır.
▸Nedeni ayırt eden tek sorgu
Sunucuya süper kullanıcı ile bağlanıp şunu çalıştırın:
SELECT count(*) AS toplam,
count(*) FILTER (WHERE state = 'active') AS aktif,
count(*) FILTER (WHERE state = 'idle') AS bosta,
count(*) FILTER (WHERE state = 'idle in transaction') AS islem_icinde_bosta
FROM pg_stat_activity;
SELECT usename, application_name, client_addr, count(*)
FROM pg_stat_activity
GROUP BY 1, 2, 3
ORDER BY 4 DESC
LIMIT 10;Sonucu şu üç senaryodan birine oturtun:
| Bulgu | Gerçek neden | Doğru çözüm |
|---|---|---|
bosta sayısı toplamın %60'ından fazla, application_name dağılımı tek uygulamada yoğun | Havuzsuz bağlantı: her pod/thread kendi bağlantısını açıyor | PgBouncer (transaction mode) |
islem_icinde_bosta > 0 ve süreler uzun | Uygulama BEGIN açıp COMMIT etmiyor | idle_in_transaction_session_timeout + kod düzeltmesi |
aktif sayısı sınıra yakın, sorgular uzun | Gerçek eşzamanlılık artmış | Kapasite artışı + sorgu optimizasyonu |
▸Adım adım çözüm
1. Sınırı doğrulayın.
SHOW max_connections;
SHOW superuser_reserved_connections;superuser_reserved_connections (varsayılan 3) sadece süper kullanıcılara ayrılmıştır; uygulamanız bu sayıya ulaşamaz. Yani gerçek kullanılabilir kapasite max_connections eksi bu değerdir.
2. Acil durumda boşta oturumları sonlandırın. Panik anında tüm bağlantıları kesmek yerine sadece boşta olanları hedefleyin:
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
AND pid <> pg_backend_pid()
AND backend_start < now() - interval '10 minutes';3. Uygulama tarafındaki sızıntıyı kapatın. idle bağlantıların çoğu, kapatılmayan bağlantılardır. Havuz kütüphanesinin max değerini max_connections'a eşitlemek yaygın ve tehlikeli bir hatadır: 4 pod × 100 bağlantı = 400 bağlantı, 100'lük sınıra çarpar. Toplam bütçeyi pod sayısına bölün.
4. Oturum sürelerine üst sınır koyun. PostgreSQL 14 ve sonrasında:
ALTER SYSTEM SET idle_session_timeout = '10min';
ALTER SYSTEM SET idle_in_transaction_session_timeout = '60s';
SELECT pg_reload_conf();idle_in_transaction_session_timeout değerini 60 saniyeden kısa tutmayın; yavaş ama meşru işlemleri de kesersiniz. Hangi oturumun kesildiğini logdan takip edin.
5. Kalıcı çözüm: bağlantı havuzu. Uygulama ile PostgreSQL arasına PgBouncer koyun. Transaction modunda 1000 uygulama bağlantısı, 20 gerçek PostgreSQL bağlantısına iner.
pool_mode = transaction seçerseniz SET, LISTEN, geçici tablo ve advisory lock gibi oturuma bağlı özellikler çalışmaz. Oturum durumu kullanan bir uygulamada session modunu seçmek zorundasınız.6. Rol bazlı sınır koyun. Tek bir uygulamanın tüm kapasiteyi yemesini engellemenin en hızlı yolu:
ALTER ROLE raporlama_kullanicisi CONNECTION LIMIT 10;▸Bunu bir daha yaşamamak için
max_connections'ı yükseltmek, ilk akla gelen ve genelde yanlış olan tepkidir. Her bağlantı yaklaşık 5-10 MB bellek tüketir; 500 bağlantı, 8 GB'lık bir sunucuda shared_buffers'a yer bırakmaz. Asıl izlenecek metrik bağlantı sayısı değil, bağlantı başına düşen iş: pg_stat_database.numbackends ile xact_commit oranını izleyin. Bağlantı sayısı sabitken işlem sayısı düşüyorsa, sorun kapasite değil kilitleme veya yavaş sorgudur.
▸İlgili Mühendislik Rehberleri ve İç Linkler
- •PostgreSQL İlk Restore Tatbikatı Runbook'u
- •PostgreSQL psql CLI Hızlı Referans
- •MySQL Lock wait timeout exceeded Teşhisi
- •Test edilen sürümler: PostgreSQL 14 / 15 / 16 / 17
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
PostgreSQL password authentication failed Hatası: Neden ve Çözüm
psql password authentication failed hatasının dört nedeni: yanlış şifre, md5/SCRAM uyuşmazlığı, pg_hba.conf sırası ve yanlış cluster. Adım adım teşhis.
MySQL ERROR 1045 Access denied: root Şifresi Sıfırlama Rehberi
MySQL 1045 hatasının dört nedeni, "using password: YES/NO" ayrımının anlamı ve kilitli kalınca --init-file ile güvenli şifre sıfırlama.
SQL Server Error 18456: State Kodlarına Göre Gerçek Neden
18456 hatasında State numarası gerçek nedeni söyler. State 5, 8, 11, 18, 38 ve 40 için ayrı çözümler, ERRORLOG okuma komutları.