There's a third case for PHP: run on a fastCGI interface. In this case, PHP processes are NOT destroyed after each request, and so persistent connections do persist. Set PHP_FCGI_CHILDREN << mysql's max_connections and you'll be fine.Persistente Verbindungen sind Verbindungen, die nach Beendigung der Skriptausführung nicht geschlossen werden. Wird eine persistente Verbindung angefordert, prüft PHP, ob bereits eine identische persistente Verbindung (die von einem früheren Aufruf offen geblieben ist) existiert; ist dies der Fall, wird sie wiederverwendet, andernfalls wird eine neue Verbindung aufgebaut. Eine "identische" Verbindung ist eine Verbindung, die zum gleichen Host mit demselben Benutzernamen und Passwort (sofern zutreffend) hergestellt wurde.
Es gibt keine Möglichkeit, eine bestimmte Verbindung anzufordern oder zu garantieren, ob die zurückgegebene Verbindung eine bestehende oder eine ganz neue ist (etwa wenn alle bestehenden Verbindungen in Verwendung sind oder die Anfrage von einem anderen Worker bearbeitet wird, der über einen eigenen Verbindungs-Pool verfügt).
Die persistenten Verbindungen von PHP können daher beispielsweise nicht verwendet werden, um:
Persistente Verbindungen bieten keinerlei Funktionalität, die nicht auch mit nicht-persistenten Verbindungen möglich wäre.
Es gibt zwei Möglichkeiten, wie ein Webserver PHP zur Generierung von Webseiten einsetzen kann:
Die erste Methode ist, PHP als CGI-"Wrapper" zu benutzen. Wenn diese Methode eingesetzt wird, wird für jede Anfrage nach einer PHP-Seite vom Webserver eine Instanz des PHP-Interpreters gestartet und anschließend wieder beendet. Durch die Beendigung des Interpreters nach jeder Anfrage werden alle Ressourcen, auf die zugegriffen wurde (wie beispielsweise eine Verbindung zu einem SQL-Datenbankserver), wieder geschlossen. In diesem Fall erreicht man nichts, wenn man persistente Verbindungen benutzt - Persistenz ist in diesem Fall nicht gegeben.
Die zweite und populärste Methode ist der Einsatz von PHP-FPM oder von PHP als Modul in einem Multiprozess-Webserver (derzeit nur Apache). Solche Umgebungen haben typischerweise einen Prozess (den Elternprozess), der eine Reihe weiterer Prozesse (seine Kinder) koordiniert, welche die eigentliche Arbeit des Bereitstellens der Webseiten übernehmen. Wenn eine Anfrage von einem Client eingeht, wird sie an eines der Kinder weitergereicht, das gerade keinen anderen Client bedient. Das bedeutet, dass eine zweite Anfrage desselben Clients an den Server unter Umständen von einem anderen Kindprozess als die erste Anfrage bearbeitet wird. Wurde eine persistente Verbindung einmal geöffnet, kann jede danach vom selben Kindprozess bediente Seite die bereits aufgebaute Verbindung zum SQL-Server weiterverwenden.
Hinweis:
Die verwendete Methode lässt sich anhand des Werts von "Server API" in der Ausgabe von phpinfo() oder anhand des Werts der Konstante
PHP_SAPI, ausgeführt über eine Web-Anfrage, prüfen.Lautet die Server API "Apache 2 Handler" oder "FPM/FastCGI", werden persistente Verbindungen über Anfragen hinweg wiederverwendet, die vom selben Worker bedient werden. Bei jedem anderen Wert bleiben persistente Verbindungen nach jeder Anfrage nicht erhalten.
Da PHP auf der Kommandozeile für jedes Skript einen neuen Prozess verwendet, werden persistente Verbindungen nicht zwischen Kommandozeilen-Skripten geteilt. Es bringt daher keinen Nutzen, sie in kurzlebigen Skripten wie Cronjobs oder einmaligen Kommandozeilenbefehlen einzusetzen. Sie können jedoch zum Beispiel in einem langlaufenden Anwendungsserver nützlich sein, der viele Anfragen oder Aufgaben bedient, von denen jede ihre eigene Datenbankverbindung benötigen kann.
Persistente Verbindungen sind nützlich, wenn der Aufwand zum Aufbau einer Verbindung zu einem SQL-Server hoch ist. Ob dieser Aufwand signifikant ist, hängt von vielen Faktoren ab, etwa von der Art der Datenbank, davon, ob sie auf demselben Rechner wie der Webserver läuft, und davon, wie stark dieser Rechner ausgelastet ist. Ist der Verbindungsaufwand hoch, können persistente Verbindungen erheblich helfen: Jeder Kindprozess verbindet sich nur einmal während seiner gesamten Lebensdauer, statt jedes Mal, wenn er eine Seite verarbeitet, die eine Verbindung zum SQL-Server benötigt. Das bedeutet, dass jeder Kindprozess, der eine persistente Verbindung öffnet, seine eigene Verbindung zum Server unterhält. Bei beispielsweise 20 verschiedenen Kindprozessen, die jeweils ein Skript ausführen, das eine persistente Verbindung zum SQL-Server aufbaut, ergeben sich 20 separate Verbindungen zu diesem Server, eine pro Kind.
Es ist jedoch zu beachten, dass dies Nachteile haben kann, wenn eine Datenbank mit Verbindungslimits verwendet wird, die durch persistente Verbindungen der Kindprozesse überschritten werden. Hat die Datenbank ein Limit von 16 gleichzeitigen Verbindungen und versuchen während einer stark ausgelasteten Server-Sitzung 17 Kindprozesse, eine Verbindung herzustellen, wird einer von ihnen fehlschlagen. Bestehen in den Skripten Fehler, die das Schließen der Verbindungen verhindern (wie etwa Endlosschleifen), können die verfügbaren 16 Verbindungen schnell aufgebraucht sein.
Persistente Verbindungen erhöhen in der Regel die Anzahl der zu einem gegebenen Zeitpunkt geöffneten Verbindungen, da untätige Worker weiterhin die Verbindungen halten, die sie für vorherige Anfragen geöffnet haben. Werden viele Worker hochgefahren, um eine Lastspitze zu bewältigen, bleiben die von ihnen geöffneten Verbindungen bestehen, bis der Worker beendet wird oder der Datenbankserver die Verbindung schließt.
Es ist sicherzustellen, dass die vom Datenbankserver erlaubte maximale Anzahl an Verbindungen größer ist als die maximale Anzahl der Worker für Web-Anfragen (zuzüglich aller weiteren Verwendungen wie Cronjobs oder administrativer Verbindungen).
Es empfiehlt sich, in der Dokumentation der Datenbank nachzuschlagen, wie der Datenbankserver aufgegebene oder im Leerlauf befindliche Verbindungen per Timeout behandelt. Lange Timeouts können die Anzahl der zu einem Zeitpunkt geöffneten persistenten Verbindungen erheblich erhöhen.
Manche Datenbank-Erweiterungen führen eine automatische Bereinigung durch, wenn die Verbindung wiederverwendet wird; andere überlassen diese Aufgabe dem Anwendungsentwickler. Je nach gewählter Datenbank-Erweiterung und Anwendungsdesign kann eine manuelle Bereinigung vor Beendigung des Skripts erforderlich sein. Änderungen, die Verbindungen in einem unerwarteten Zustand zurücklassen können, sind unter anderem:
Tabellensperren und Transaktionen, die nicht aufgeräumt oder abgeschlossen werden, können dazu führen, dass andere Abfragen unbegrenzt blockiert werden und/oder dass eine spätere Wiederverwendung der Verbindung unerwartete Änderungen verursacht.
Ist die falsche Datenbank ausgewählt, kann eine spätere Wiederverwendung der Verbindung Abfragen nicht wie erwartet ausführen (oder führt sie auf der falschen Datenbank aus, wenn sich die Schemata ausreichend ähneln).
Werden temporäre Tabellen nicht aufgeräumt, können nachfolgende Anfragen dieselbe Tabelle nicht erneut anlegen.
Die Bereinigung kann mithilfe von Klassen-Destruktoren oder register_shutdown_function() umgesetzt werden. Dedizierte Connection-Pooling-Proxies, die dies als Teil ihrer Funktionalität enthalten, können ebenfalls in Betracht gezogen werden.
Aufgrund des oben beschriebenen Verhaltens und der potenziellen Nachteile sollten persistente Verbindungen nicht ohne sorgfältige Abwägung eingesetzt werden. Sie sollten nicht ohne zusätzliche Anpassungen der Anwendung sowie ohne sorgfältige Konfiguration von Datenbankserver und Webserver und/oder PHP-FPM verwendet werden.
Es sollten alternative Lösungen in Betracht gezogen werden, etwa die Untersuchung und Behebung der Ursachen für den Verbindungsaufbau-Overhead (beispielsweise das Deaktivieren von Reverse-DNS-Lookups auf dem Datenbankserver) oder dedizierte Connection-Pooling-Proxies.
Für Web-APIs mit hohem Anfragevolumen sollten alternative Runtimes oder langlaufende Anwendungsserver in Betracht gezogen werden.
There's a third case for PHP: run on a fastCGI interface. In this case, PHP processes are NOT destroyed after each request, and so persistent connections do persist. Set PHP_FCGI_CHILDREN << mysql's max_connections and you'll be fine.In IBM_DB2 extension v1.9.0 or later performs a transaction rollback on persistent connections at the end of a request, thus ending the transaction. This prevents the transaction block from carrying over to the next request which uses that connection if script execution ends before the transaction block does.One additional not regarding odbc_pconnect and possibly other variations of pconnect:
If the connection encounters an error (bad SQL, incorrect request, etc), that error will return with be present in odbc_errormsg for every subsequent action on that connection, even if subsequent actions don't cause another error.
For example:
A script connects with odbc_pconnect.
The connection is created on it's first use.
The script calls a query "Select * FROM Table1".
Table1 doesn't exist and odbc_errormsg contains that error.
Later(days, perhaps), a different script is called using the same parameters to odbc_pconnect.
The connection already exists, to it is reused.
The script calls a query "Select * FROM Table0".
The query runs fine, but odbc_errormsg still returns the error about Table1 not existing.
I'm not seeing a way to clear that error using odbc_ functions, so keep your eyes open for this gotcha or use odbc_connect instead.For the oci8 extension it is not true that " [...] when using transactions, a transaction block will also carry over to the next script which uses that connection if script execution ends before the transaction block does.". The oci8 extension does a rollback at the end scripts using persistent connections, thus ending the transaction. The rollback also releases locks. However any ALTER SESSION command (e.g. changing the date format) on a persistent connection will be retained over to the next script.It seems that using pg_pconnect() will not persist the temporary views/tables. So if you are trying to create temporary views/tables with the query results and then access them with the next script of the same session, you are out of luck. Those temporary view/tables are gone after each PHP script ended. One way to get around this problem is to create real view/table with session ID as part of the name and record the name&creation time in a common table. Have a garbage collection script to drop the view/table who's session is expired.If anyone ever wonders why the number of idle db process (open connections) seems to grow even though you are using persistent connections, here's why:
"You are probably using a multi-process web server such as Apache. Since
database connections cannot be shared among different processes a new
one is created if the request happen to come to a different web server
child process."To those using MySQL and finding a lot of leftover sleeping processes, take a look at MySQL's wait_timeout directive. By default it is set to 8 hours, but almost any decent production server will have been lowered to the 60 second range. Even on my testing server, I was having problems with too many connections from leftover persistent connections.