mirror of
https://github.com/php/doc-en.git
synced 2026-03-23 23:32:18 +01:00
Affects files: - `features/persistent-connections.xml` - `reference/datetime/examples.xml`
234 lines
10 KiB
XML
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
|
|
-->
|