dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Hata Kütüphanesi/PostgreSQL/postgresql-too-many-clients
PostgreSQL
PG 14 - 17
5 dk okuma
FATAL: sorry, too many clients already

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ü.

Standart:Kıdemli Veritabanı Mimarı & SRE (dataiotech Labs)
Test Edilen Sürümler: PostgreSQL 14 / 15 / 16 / 17
İlk 60 Saniye Teşhis Protokolü:

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:

plaintext
FATAL: sorry, too many clients already

Bu, 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:

sql
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:

BulguGerçek nedenDoğru çözüm
bosta sayısı toplamın %60'ından fazla, application_name dağılımı tek uygulamada yoğunHavuzsuz bağlantı: her pod/thread kendi bağlantısını açıyorPgBouncer (transaction mode)
islem_icinde_bosta > 0 ve süreler uzunUygulama BEGIN açıp COMMIT etmiyoridle_in_transaction_session_timeout + kod düzeltmesi
aktif sayısı sınıra yakın, sorgular uzunGerçek eşzamanlılık artmışKapasite artışı + sorgu optimizasyonu

▸Adım adım çözüm

1. Sınırı doğrulayın.

sql
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:

sql
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle' AND pid <> pg_backend_pid() AND backend_start < now() - interval '10 minutes';
[!WARNING] Bunu bir script'e bağlayıp sürekli çalıştırmayın — bu bir ilk yardım, tedavi değil. Kalıcı hale getirirseniz bağlantı havuzunuzun sürekli sıfırlanmasına ve bağlantı fırtınasına yol açarsınız.

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:

sql
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.

[!IMPORTANT] 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:

sql
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

Diğer Veritabanı Hata Teşhisleri

Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.

Tüm Hatalar (20)