PostgreSQL-Fehler: sorry, too many clients already
FATAL: sorry, too many clients already
Jeder Verbindungs-Slot auf dem Server ist belegt, daher verweigert PostgreSQL den neuen. Der Server ist ansonsten gesund — er ist einfach voll. Eine nahe Variante desselben Problems ist die Meldung über "remaining connection slots are reserved": die letzten paar Slots werden für Superuser zurückgehalten, damit ein Administrator noch hineinkommen und die Dinge in Ordnung bringen kann.
Was dieser Fehler bedeutet
PostgreSQL akzeptiert höchstens max_connections gleichzeitige Verbindungen (Standard: 100) und reserviert einige davon (superuser_reserved_connections, Standard: 3) für Superuser. Wenn ein regulärer Client eine Verbindung über das nicht reservierte Limit hinaus anfordert, erhält er dieses FATAL zum Verbindungszeitpunkt — die Verbindung wird verweigert, nichts anderes auf dem Server ist betroffen.
Jede Verbindung ist ein eigener Serverprozess mit eigenem Speicher, daher existiert das Limit aus gutem Grund: PostgreSQL verkraftet Tausende direkter Verbindungen nicht anmutig. Deshalb ist die dauerhafte Lösung fast nie "die Zahl erhöhen".
Häufige Ursachen
- Kein Connection-Pooler vor der Datenbank, mit vielen Anwendungsinstanzen, die jeweils ihren eigenen Pool öffnen. Zehn Dienste × 20 Verbindungen je = 200 vor jeder Lastspitze.
- Connection-Leaks: Codepfade, die Verbindungen öffnen und nie an den Pool zurückgeben.
- Sitzungen, die in
idle in transactionfesthängen und Slots (sowie Locks und Vacuum-Fortschritt) unbegrenzt halten. - Serverless-/Autoscaling-Worker, die pro Aufruf frische Verbindungen öffnen.
- Eine Verlangsamung an anderer Stelle: wenn Queries plötzlich 10× länger dauern, stauen sich Verbindungen, während Aufrufer in ein Timeout laufen und erneut versuchen. Der Fehler ist das Symptom; die langsame Query ist die Krankheit.
So diagnostizieren Sie ihn
Verbinden Sie sich als Superuser (dafür sind die reservierten Slots da) und schauen Sie, wer die Slots hält:
SHOW max_connections;
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state ORDER BY count(*) DESC;
SELECT usename, application_name, count(*)
FROM pg_stat_activity
GROUP BY 1, 2 ORDER BY count(*) DESC;
-- Sitzungen, die am längsten in einer Transaktion sind (Leak-Kandidaten):
SELECT pid, usename, state, now() - xact_start AS xact_age, left(query, 60)
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_start
LIMIT 10;
Viele idle-Verbindungen deuten auf überdimensionierte oder leckende Anwendungs-Pools hin; alte idle in transaction-Sitzungen deuten auf Anwendungscode hin, der eine Transaktion geöffnet und sich davongemacht hat.
So beheben Sie ihn
- Setzen Sie einen Pooler davor (PgBouncer im Transaction-Modus ist die Standardantwort): Tausende Client-Verbindungen werden auf ein paar Dutzend Server-Verbindungen multiplext. Das ist die Lösung, die skaliert; prüfen Sie zuerst, dass Ihre Arbeitslast nicht auf Sitzungszustand angewiesen ist (Sitzungs-
SET, Advisory Locks, Prepared Statements über Transaktionen hinweg), den das Transaction-Pooling nicht erhält. - Beheben Sie die Leaks: begrenzen Sie jeden Pool (max. Größe, max. Lebensdauer, Idle-Timeout) und stellen Sie sicher, dass Verbindungen in einem
finally-artigen Cleanup zurückgegeben werden. - Begrenzen Sie den Schaden serverseitig:
ALTER ROLE app_user CONNECTION LIMIT 50; ALTER SYSTEM SET idle_in_transaction_session_timeout = '5min'; SELECT pg_reload_conf(); - Erhöhen Sie
max_connectionsnur bewusst (erfordert einen Neustart): jeder Slot ist ein Prozess mit realen Speicherkosten, und Hunderte aktive Backends bringen meist schlechtere Leistung als ein gepooltes paar Dutzend.
idle in transaction-Sitzungen fressen nicht nur Slots: sie halten das Vacuum für die gesamte Datenbank zurück.
