Persistent connections are SQL 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).
Note: There are other extensions that provide persistent connections, such as the IMAP extension.
People who aren't thoroughly familiar with the way web servers work and distribute the
load may mistake persistent connects for what they're not. In particular, they do not
give you an ability to open 'user sessions' on the same SQL link, they do not give you
an ability to build up a transaction efficiently, and they don't do a whole lot of other things. In
fact, to be extremely clear about the subject, persistent connections don't give you
any functionality that wasn't possible with their non-persistent
brothers.
Why?
This has to do with the way web servers work. There are three ways in which your web
server can utilize PHP to generate web pages.
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.
The second, and most popular, method is to run PHP as a module in a multiprocess web
server, which currently only includes Apache. A multiprocess server typically has one process (the
parent) which coordinates a set of processes (its children) who actually do the work of serving up
web pages. When each 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 serviced by a different child process than the first time. What a
persistent connection does for you in this case it make it so each child process only needs to
connect to your SQL server the first time that it serves a page that makes us of such a connection.
When another page then requires a connection to the SQL server, it can reuse the connection that
child established earlier.
The last method is to use PHP as a plug-in for a multithreaded web server. Currently
PHP 4 has support for ISAPI, WSAPI, and NSAPI (on Windows), which all allow PHP to be used as a
plug-in on multithreaded servers like Netscape FastTrack (iPlanet), Microsoft's Internet
Information Server (IIS), and O'Reilly's WebSite Pro. The behavior is essentially the same as for
the multiprocess model described before. Note that SAPI support is not available in PHP
3.
If persistent connections don't have any added functionality, what are they good
for?
The answer here is extremely simple -- efficiency. 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.
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), a database with only 32 connections may be
rapidly swamped. Check your database documentation for information on handling abandoned or idle
connections.
| Warning |
|
There are a couple of additional caveats to keep in mind when using persistent
connections. One is that when using table locking on a persistent connection, if the script for
whatever reason cannot release the lock, then subsequent scripts using the same connection will
block indefinitely and may require that you either restart the httpd server or the database server.
Another is 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. In
either case, you can use
register_shutdown_function() to register a simple cleanup function to unlock your tables or
roll back your transactions. Better yet, avoid the problem entirely by not using persistent
connections in scripts which use table locks or transactions (you can still use them
elsewhere).
|
An important summary. Persistent connections were designed to have one-to-one
mapping to regular connections. That means that you should always be able to replace
persistent connections with non-persistent connections, and it won't change the way your script
behaves. It may (and probably will) change the efficiency of the script, but not its
behavior!
See also fbsql_pconnect(), ibase_pconnect(), ifx_pconnect(),
imap_popen(), ingres_pconnect(), msql_pconnect(), mssql_pconnect(),
mysql_pconnect(), OCIPLogon(),
odbc_pconnect(), Ora_pLogon(),
pfsockopen(), pg_pconnect(), and sybase_pconnect().
|