1
0
mirror of https://github.com/php/doc-en.git synced 2026-03-23 23:32:18 +01:00
Files
archived-doc-en/features/persistent-connections.xml
Marcos Porto Mariño cd8b964b85 Fix indentation and remove useless wrapping para tag (#4982)
Affects files:
- `features/persistent-connections.xml`
- `reference/datetime/examples.xml`
2025-11-10 03:16:31 +00:00

234 lines
10 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<chapter xml:id="features.persistent-connections" xmlns="http://docbook.org/ns/docbook">
<title>Persistent Database Connections</title>
<simplesect>
<title>What are Persistent Connections?</title>
<simpara>
Persistent connections are links that do not close when the
execution of your script ends. When a persistent connection is
requested, PHP checks if there's already an identical persistent
connection (that remained open from earlier) - and if it exists, it
uses it. If it does not exist, it creates the link. An 'identical'
connection is a connection that was opened to the same host, with
the same username and the same password (where applicable).
</simpara>
<simpara>
There's no method of requesting a specific connection, or guaranteeing
whether you get an existing connection or a brand new one (if all existing
connections are in use, or the request is being served by a different worker,
which has a separate pool of connections).
</simpara>
<simpara>
This means that you cannot use PHP's persistent connections to, for example:
</simpara>
<simplelist>
<member>assign a specific database session to a specific web user</member>
<member>create a large transaction across multiple requests</member>
<member>initiate a query on one request and collect the results on another</member>
</simplelist>
<simpara>
Persistent connections do not give you <emphasis>any</emphasis>
functionality that wasn't possible with non-persistent connections.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.web">
<title>Web Requests</title>
<simpara>
There are two ways in which your web server can utilize PHP to generate
web pages:
</simpara>
<simpara>
The first method is to use PHP as a CGI "wrapper". When run this
way, an instance of the PHP interpreter is created and destroyed
for every page request (for a PHP page) to your web server.
Because it is destroyed after every request, any resources that it
acquires (such as a link to an SQL database server) are closed when
it is destroyed. In this case, you do not gain anything from trying
to use persistent connections - they simply don't persist.
</simpara>
<simpara>
The second, and most popular, method is to run PHP-FPM, or PHP as a module
in a multiprocess web server, which currently only includes Apache.
These setups typically have one process (the parent) which
coordinates a set of processes (its children) who actually do the
work of serving up web pages. When a request comes in from a
client, it is handed off to one of the children that is not already
serving another client. This means that when the same client makes
a second request to the server, it may be served by a different
child process than the first time. When opening a persistent connection,
every following page requesting SQL services can reuse the same
established connection to the SQL server.
</simpara>
<note>
<para>
You can check which method your web requests use by checking the value of
"Server API" in the output of <function>phpinfo</function> or the value of
<constant>PHP_SAPI</constant>, run from a web request.
</para>
<para>
If the Server API is "Apache 2 Handler" or "FPM/FastCGI", then persistent
connections will be used across requests served by the same worker. For any
other value, persistent connections will not persist after each request.
</para>
</note>
</simplesect>
<simplesect xml:id="persistent-connections.cli">
<title>Command-line Processes</title>
<simpara>
As command-line PHP uses a new process for each script, persistent
connections are not shared between command-line scripts, so there is no
value in using them in transient scripts such as crons or commands.
However, they may be useful if, for example, you're writing a long-running
application server that serves many requests or tasks and each may need
their own database connection.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.why">
<title>Why Use Them?</title>
<simpara>
Persistent connections are good if the overhead to create a link to your
SQL server is high. Whether or not this overhead is really high depends
on many factors. Like, what kind of database it is, whether or not
it sits on the same computer on which your web server sits, how
loaded the machine the SQL server sits on is and so forth. The
bottom line is that if that connection overhead is high, persistent
connections help you considerably. They cause the child process to
simply connect only once for its entire lifespan, instead of every
time it processes a page that requires connecting to the SQL
server. This means that for every child that opened a persistent
connection will have its own open persistent connection to the
server. For example, if you had 20 different child processes that
ran a script that made a persistent connection to your SQL server,
you'd have 20 different connections to the SQL server, one from
each child.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.drawbacks.conn-limits">
<title>Potential Drawbacks: Connection Limits</title>
<simpara>
Note, however, that this can have some drawbacks if you are using a
database with connection limits that are exceeded by persistent
child connections. If your database has a limit of 16 simultaneous
connections, and in the course of a busy server session, 17 child
threads attempt to connect, one will not be able to. If there are
bugs in your scripts which do not allow the connections to shut
down (such as infinite loops), the database with only 16 connections
may be rapidly swamped.
</simpara>
<simpara>
Persistent connections will usually increase the number of connections open
at any given time because idle workers will still hold the connections for
the previous requests they served. If a large number of workers is spun up to
handle an influx of requests, the connections they opened will remain until
the worker is killed or the database server closes the connection.
</simpara>
<simpara>
Ensure that the maximum number of connections allowed by the database server
is greater than the maximum number of web request workers (plus any other
usage such as crons or administrative connections).
</simpara>
<simpara>
Check your database documentation for information on handling abandoned or
idle connections (timeouts). Long timeouts may significantly increase the
number of persistent connections open at any one time.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.drawbacks.state">
<title>Potential Drawbacks: Maintaining Connection State</title>
<simpara>
Some database extensions perform automatic cleanup when the connection is
reused; others leave this task at the discretion of the application developer.
Depending on the chosen database extension and the application design, manual
cleanup may be needed before the script exits. Changes that may leave
connections in an unexpected state include:
</simpara>
<simplelist>
<member>Selected / default database</member>
<member>Table locks</member>
<member>Uncommitted transactions</member>
<member>Temporary tables</member>
<member>Connection specific settings or features such as profiling</member>
</simplelist>
<simpara>
Table locks and transactions that are not cleaned up or closed may cause
other queries to be blocked indefinitely and/or cause subsequent reuse of
the connection to cause unexpected changes.
</simpara>
<simpara>
Having the wrong database selected will cause subsequent reuse of the
connection to be unable to execute queries as expected (or execute them on
the wrong database if schemas are similar enough).
</simpara>
<simpara>
If temporary tables are not cleaned up, subsequent requests will not be able
to recreate the same table.
</simpara>
<simpara>
You can implement cleanup using class destructors or
<function>register_shutdown_function</function>. You may also want to
consider dedicated connection pooling proxies that include this as part of
their functionality.
</simpara>
</simplesect>
<simplesect xml:id="persistent-connections.final-words">
<title>Final Words</title>
<simpara>
Given their behavior and potential drawbacks described above, you should not
use persistent connections without careful consideration. They should not be
used without implementing additional changes to your application and careful
configuration of your database server and web server and/or PHP-FPM.
</simpara>
<simpara>
Consider alternative solutions such as investigating and fixing the causes of
connection creation overheads (for example, disabling reverse DNS lookups on
the database server), or dedicated connection pooling proxies.
</simpara>
<simpara>
For high volume web APIs, consider using alternative runtimes or long-running
application servers.
</simpara>
</simplesect>
<simplesect role="seealso" xml:id="persistent-connections.seealso">
&reftitle.seealso;
<simplelist>
<member><function>ibase_pconnect</function></member>
<member><function>oci_pconnect</function></member>
<member><function>odbc_pconnect</function></member>
<member><function>pfsockopen</function></member>
<member><function>pg_connect</function></member>
<member><link linkend="mysqli.persistconns">MySQLi and Persistent Connections</link></member>
<member><link linkend="pdo.connections">PDO Connection Management</link></member>
</simplelist>
</simplesect>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->