What are the rules/logic behind persistent connection management when using PDO?
Web Server
DB Server
Non-persistent connections
<?php // Open a new connection // Session created in Oracle $dbh = new PDO('DSN', 'webuser', 'password'); // webuser is active in v$session with a SID=1 $dbh = NULL; // webuser removed from v$session // Manually calling $dbh = NULL; will remove the session from v$session // OR // Wait for script EOL so a kill-session command is sent to Oracle? ?>
Persistent connections
<?php // Open a new connection and make it persistent // Session created in Oracle // Is Apache maintaining some sort of keep-alive with Oracle here? // because I thought php.exe is only alive for the duration of the script $dbh = new PDO('DSN', 'webuser', 'password', array(PDO::ATTR_PERSISTENT => TRUE)); // webuser is active in v$session with a SID=1 $dbh = NULL; // webuser is still active in v$session with a SID=1 $dbh = new PDO('DSN', 'webuser', 'password', array(PDO::ATTR_PERSISTENT => TRUE)); // webuser is still active in v$session with a SID=1 // Manually calling $dbh = NULL; does not kill session // OR // Script EOL does not kill session // ^^ this is good, just as expected ?>
I visit the page and webuser
gets a SID=1
My colleague visits the page and webuser
gets an additional SID=2
<- rinse, repeat, and increment SID for new computers visiting this page
Shouldn't a new visitor be re-using SID=1
?
All answers, suggestions, requests for alternate testing, links to reading material are welcomed.
I have RTFM'ed for a while and Googling has only produced meager Advantages of Persistent vs. Non-persistent
blogs.
The connection remains active for the lifetime of that PDO object. To close the connection, you need to destroy the object by ensuring that all remaining references to it are deleted—you do this by assigning null to the variable that holds the object.
The persistent connection cache allows you to avoid the overhead of establishing a new connection every time a script needs to talk to a database, resulting in a faster web application.
PDO - PHP Data Object. A set of PHP extensions that provide a core PDO class and database specific drivers. Provides a vendor-neutral lightweight data-access abstraction layer. Focus on data access abstraction rather than database abstraction.
dsn. The Data Source Name, or DSN, contains the information required to connect to the database. In general, a DSN consists of the PDO driver name, followed by a colon, followed by the PDO driver-specific connection syntax. Further information is available from the PDO driver-specific documentation.
Apache has one parent process. This process creates child processes that will handle any requests coming to the web server. The initial amount of child processes being started when the web server starts is configured by the StartServers
directive in the apache configuration. The number goes up as needed with a raising amount of requests hitting the web server until ServerLimit
is reached.
If PHP (ran as mod_php, as CGI all resources are freed at the end of script execution) is now being told to establish a persistent connection with a database for a request, this connection is hold even after the script finishes. The connection being now hold is a connection between the apache child process which the request was handled by and the database server and can be re-used by any request that is being handled by this exact child process.
If, for some reason (do not ask me exactly why), the child process is being occupied longer than the actual request and another request comes in, the parent apache process redirects this request to a (new) child process which may has not established a connection to the database up to this time. If it has to during the execution of the script, it raises the SID as you have observed. Now there are two connections be hold by two different child processes of apache.
It is important to know, that this can also cause a lot of trouble. If there is an endless loop or an aborted transaction or some other may be even unpredictable error during the script execution, the connection is blocked and can not be re-used. Also it could happen that all of the available connections of the database are used, but there is another child process of the apache server trying to access the database. This process is blocked for the time being until a connection is freed by the database or apache (timeout or voluntarily by termination). Any further information about this topic on this page: http://www.php.net/manual/en/features.persistent-connections.php
I hope I got all that we have discussed in our comment conversation summarized correctly and did not forget anything. If so, please, leave me a hint and I will add it. :)
Edit:
I just finished reading the article @MonkeyZeus mentioned in this comment. It describes the process I summarized above and provides useful information on how to optimize your apache server to work better together with persistent connections. It can be used with or without oracle database backends, though. You should give a look: http://www.oracle.com/technetwork/articles/coggeshall-persist-084844.html
From the manual page of php
for persistent connections on this link:
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.
The reason behind using persistent connections is, of course, reducing the number of connections which are rather expensive; Even though they are much faster with MySQL than with most other databases.
There are some issues with table locking while using persistent connections.
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 by mysql commit.
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.
I suggest you read this question about disatvantages of persistent connections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With