Erschöpfte Datenbankverbindungen in PHP äußern sich häufig durch sporadische Fehler: Einige Anfragen schlagen fehl, andere warten, und bei hoher Auslastung verschärft sich das Problem. Eine Erhöhung des Verbindungslimits kann Abhilfe schaffen, die Überlastung jedoch auch auf den Datenbankserver verlagern. Die Lösung beginnt damit, festzustellen, welche Ressource erschöpft ist und wodurch die Verbindungen belegt bleiben.
Symptome erkennen und den Fehler eingrenzen

Achten Sie auf Fehlermeldungen wie „too many connections“, Fehler beim Öffnen einer Verbindung, abgelaufene Timeouts oder Anfragen, die die maximale Ausführungszeit überschreiten. Setzen Sie ihre Häufigkeit in Beziehung zum Datenverkehr und zu weiteren Messwerten: Anwendungslatenz, CPU- und Speicherauslastung, Datenbankfehler und Anfragedauer.
Der Unterschied zwischen hoher und niedriger Auslastung liefert einen ersten Hinweis. Treten die Fehler während Spitzen auf und verschwinden, sobald der Datenverkehr zurückgeht, könnte ein Limit für gleichzeitige Verbindungen erreicht sein. Bleiben sie auch bei wenigen Anfragen bestehen, untersuchen Sie zurückgehaltene Verbindungen, blockierte Prozesse, lang laufende Abfragen oder eine nicht erreichbare Datenbank. Prüfen Sie auch, ob andere Dienste dasselbe Limit nutzen: PHP ist nicht unbedingt der einzige Verbraucher.
Erschöpfte Verbindungen von langsamen Abfragen und Sperren unterscheiden
Diese Probleme hängen zusammen, sind aber nicht gleichbedeutend. Bei einer erschöpften Verbindungskapazität ist kein Platz mehr frei, um eine weitere Verbindung zu öffnen. Eine langsame Abfrage belegt eine Verbindung länger und kann durch ihre Häufung die Verbindungskapazität erschöpfen. Bei einer Sperre wartet eine Abfrage darauf, dass eine andere Transaktion Ressourcen freigibt. Eine Nichtverfügbarkeit bedeutet, dass die Datenbank aus einem umfassenderen Grund keine Verbindungen annehmen oder bedienen kann.
Prüfen Sie die Meldung und den Fehlerpunkt. Scheitert die Anfrage, bevor eine Abfrage ausgeführt wird, untersuchen Sie den Verbindungsaufbau und das erreichte Limit. Wird die Verbindung hergestellt und dauert es anschließend lange, prüfen Sie die laufenden Abfragen, ihre Laufzeiten, Wartezeiten und offenen Transaktionen. Schließen Sie nicht allein deshalb auf „zu wenige Verbindungen“, weil die Anwendung langsam reagiert: Eine Erhöhung des Limits behebt weder eine kostspielige Abfrage noch eine Sperre.
Die PHP-Parallelität mit dem Datenbanklimit abgleichen
Im üblichen PHP-Modell, in dem Prozesse Anfragen bearbeiten, kann jeder Prozess eine Verbindung benötigen, während er mit der Datenbank arbeitet. Der potenzielle Bedarf hängt davon ab, wie viele Prozesse gleichzeitig arbeiten können, wie viele Verbindungen jeder Prozess öffnet und wie lange er sie beibehält. Auch Verbindungen von Hintergrundjobs, Konsolenbefehlen und anderen Diensten müssen berücksichtigt werden.
Erstellen Sie eine konservative Schätzung für den ungünstigsten Fall: Multiplizieren Sie die maximale effektive Parallelität jeder Prozessgruppe mit der Zahl gleichzeitiger Verbindungen, die jeder Prozess verwenden kann, und addieren Sie die Verbraucher, die sich die Datenbank teilen. Vergleichen Sie das Ergebnis mit dem konfigurierten Limit und lassen Sie Spielraum für administrative Vorgänge und Lastschwankungen. Gehen Sie nicht davon aus, dass jede Anfrage immer einer Verbindung entspricht: Der Lebenszyklus hängt vom Datenbank-Client, der Konfiguration und dem Nutzungsmuster ab.
Prüfen Sie außerdem, wie die Last verteilt ist. Mehrere PHP-Instanzen können ihre lokalen Limits einhalten und gemeinsam dennoch das Verbindungslimit der Datenbank überschreiten. Horizontale Skalierung erhöht die potenzielle Parallelität; ohne Neuberechnung der Gesamtzahl der Verbindungen ist sie keine sichere Gegenmaßnahme.
Von beiden Seiten aus messen
Stellen Sie anhand von Zeitstempeln einen Zusammenhang zwischen Anwendungs- und Datenbankmetriken her. Erfassen Sie in PHP die Anfragedauer, Verbindungsfehler, Timeouts und die Anzahl ausgelasteter Prozesse. Prüfen Sie in der Datenbank aktive und maximale Verbindungen, Zurückweisungen, laufende Abfragen, das Alter der Sitzungen und die in der Datenbank-Engine verfügbaren Warteinformationen.
Vermeiden Sie es, Zugangsdaten, vollständige Verbindungszeichenfolgen oder vertrauliche Abfragedaten zu protokollieren. Wenn die Datenbank-Engine Sitzungen und Zustände identifizieren kann, nutzen Sie diese Informationen, um inaktive Verbindungen von aktiven Abfragen oder ausstehenden Transaktionen zu unterscheiden. Vergleichen Sie die Protokolle beider Seiten: Ein Verbindungsspitzenwert parallel zu ausgelasteten PHP-Prozessen deutet auf Parallelität hin; viele alte Sitzungen oder inaktive Prozesse sprechen für zurückgehaltene Verbindungen; wenige lang laufende Abfragen können erklären, warum das Limit nach und nach ausgeschöpft wird.
Die Instrumentierung sollte drei Fragen beantworten: Wie viele Verbindungen werden genutzt, wie lange dauern sie, und welche Arbeit hält sie belegt? Ohne diese zeitliche Übersicht bringt die Änderung von Limits oder die Aktivierung persistenter Verbindungen weitere Variablen ins Spiel und erschwert die Ursachenfindung.
Persistente und langlebige Verbindungen bewerten
Eine persistente Verbindung kann die Kosten für wiederholtes Öffnen von Verbindungen senken, insbesondere wenn die Umgebung Prozesse über mehrere Anfragen hinweg beibehält. Eine Verbindung, die einem Prozess zugeordnet bleibt, kann jedoch auch dann einen Platz belegen, wenn keine Abfragen ausgeführt werden. Bei vielen Prozessen oder mehreren Instanzen kann die Summe der zurückgehaltenen Verbindungen das Datenbanklimit erreichen.
Prüfen Sie den tatsächlichen Lebenszyklus des Prozesses und des Treibers, bevor Sie persistente Verbindungen aktivieren oder deaktivieren. Vergewissern Sie sich, wie die Sitzung wiederverwendet wird und ob die Anwendung zwischen Anfragen den erwarteten Zustand wiederherstellt, etwa Transaktionen, Sitzungsvariablen oder verbindungsspezifische Einstellungen. Persistente Verbindungen sind kein universeller Pool und garantieren keinen geringeren Verbrauch. Testen Sie sie unter repräsentativer Last und beobachten Sie die maximale Verbindungszahl, die Latenz und den verbleibenden Zustand.
Mitigationen schrittweise und evidenzbasiert umsetzen
- Parallelität begrenzen. Passen Sie die PHP-Prozesszahl oder die Parallelität der Worker so an, dass der gleichzeitige Bedarf mit dem gemeinsam genutzten Kontingent vereinbar ist. Dadurch sinkt der Druck, allerdings können Warteschlange und Latenz zunehmen, wenn die Kapazität unter dem anhaltenden Bedarf liegt.
- Ressourcen freigeben, sobald sie nicht mehr benötigt werden. Schließen Sie Verbindungen ausdrücklich, sofern Bibliothek und Ausführungsmuster dies zulassen, und vermeiden Sie es, sie während datenbankunabhängiger Arbeit beizubehalten. Beachten Sie, dass das Schließen einer persistenten Verbindung die physische Verbindung auf dem Server nicht unbedingt freigibt: Das Ergebnis hängt vom Treiber und vom Lebenszyklus des Prozesses ab. Prüfen Sie offene Transaktionen und Fehlerpfade, bei denen die Bereinigung nicht abgeschlossen wird.
- Die Belegungsdauer verkürzen. Analysieren Sie langsame Abfragen, Indizes, das Ergebnisvolumen und Transaktionen. Die Optimierung eines Vorgangs, der eine Verbindung lange belegt, kann den gleichzeitigen Bedarf senken, ohne das Limit zu erhöhen.
- Limits erst nach Messungen anpassen. Eine Erhöhung des Maximums kann sinnvoll sein, wenn in der Datenbank noch CPU- und Speicherkapazität vorhanden ist und der neue ungünstigste Fall tragbar bleibt. Andernfalls können sich mehr Arbeit und eine stärkere Überlastung aufbauen.
Nehmen Sie jeweils nur eine Änderung vor, dokumentieren Sie den vorherigen Zustand und legen Sie eine Bedingung für den Rollback fest. Ist das System bereits beeinträchtigt, kann eine vorübergehende Verringerung der Parallelität sicherer sein als ein gleichzeitiger Neustart aller Prozesse, der eine neue Verbindungsspitze verursachen könnte.
Wann ein Verbindungspool oder -proxy sinnvoll sein kann
Ein Pool oder Proxy kann physische Verbindungen wiederverwenden und steuern, wie viele Verbindungen die Datenbank-Engine erreichen. Das ist nützlich, wenn viele Anwendungsprozesse kurzlebige Verbindungen nutzen. Die gleichzeitige Arbeit wird dadurch nicht beseitigt und Abfragen werden nicht schneller; vielmehr kommt eine weitere Schicht mit eigener Kapazität, Warteschlangen, Limits und Betriebsmodi hinzu.
Prüfen Sie vor der Einführung die Kompatibilität mit der Datenbank-Engine, dem PHP-Treiber, der Authentifizierung, der Transaktionsnutzung und dem Sitzungszustand. Untersuchen Sie, wie der Proxy mit langen Verbindungen, Wiederverbindungen und Ausfällen umgeht, und legen Sie Metriken sowie Betriebsverfahren fest. Validieren Sie die Konfiguration mit Tests, die die tatsächliche Parallelität abbilden: Eine Konfiguration, die in der Entwicklung funktioniert, kann sich unter hoher Last anders verhalten.
Wiederherstellung vorbereiten und erneute Vorfälle vermeiden

Richten Sie Warnmeldungen für Verbindungen nahe am Limit, Zurückweisungen, Abfragedauer und die Auslastung der PHP-Prozesse ein. Ergänzen Sie einen repräsentativen Lasttest, der Instanzen, Hintergrundjobs und weitere Verbraucher einbezieht; prüfen Sie den ungünstigsten Fall, nicht nur den Durchschnitt. Halten Sie ein Betriebsverfahren bereit, das festlegt, was zu messen ist, wie die Parallelität begrenzt wird, wer das Verbindungslimit ändern darf und wann ein Rollback erfolgt.
Untersuchen Sie nach der Wiederherstellung des Dienstes die Abfolge vor dem Vorfall: Änderungen am Datenverkehr, Deployments, neue Abfragen, Wachstum der Prozesszahl oder fehlgeschlagene Bereinigungen. Ziel ist es, Ursache und Wirkung anhand von Daten zu verknüpfen. Zeigen die Metriken zurückgehaltene Verbindungen, korrigieren Sie deren Lebenszyklus; dominiert die Abfragedauer, optimieren Sie die Abfragen; übersteigt die legitime Parallelität die Kapazität, dimensionieren und begrenzen Sie sie anhand eines expliziten Verbindungsbudgets.



