完全理解 PDO ATTR_PERSISTENT
使用 PDO 时持久连接管理背后的规则/逻辑是什么?
What are the rules/logic behind persistent connection management when using PDO?
网络服务器
- Windows 7 x64
- 双核,16GB RAM
- Apache 2.2.17
- PHP 5.3.5
- 通过带有 IP 地址、端口、服务名称等的 DSN 字符串连接...
- 没有用于 DB conn 的 ODBC(现在已经尝试创建一个 2 小时了,感谢 Oracle!)
数据库服务器
- Linux 上的 Oracle 10g
- 具有 4GB RAM 的多核
- 专门为我的网络应用创建的用户名(是的,它是假的)
- 用户:网络用户
非持久连接
<?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? ?>
- 脚本可靠地执行大约需要大约 0.09 秒,框架开销等...
持久连接
<?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 ?>
- 脚本在初次访问时需要约 .12 秒来执行,并带有框架开销等......
- 后续执行 take ~.04
我访问该页面,
webuser
得到一个SID=1
I visit the page and
webuser
gets aSID=1
我的同事访问了该页面,
webuser
获得了一个额外的SID=2
<- 为访问此页面的新计算机冲洗、重复和增加 SIDMy colleague visits the page and
webuser
gets an additionalSID=2
<- rinse, repeat, and increment SID for new computers visiting this page新访问者不应该重复使用
SID=1
吗?Shouldn't a new visitor be re-using
SID=1
?欢迎所有答案、建议、替代测试请求、阅读材料链接.
All answers, suggestions, requests for alternate testing, links to reading material are welcomed.
我已经使用 RTFM 一段时间了,而谷歌搜索只产生了微薄的
持久性与非持久性的优势
博客.I have RTFM'ed for a while and Googling has only produced meager
Advantages of Persistent vs. Non-persistent
blogs.推荐答案
Apaches 的观点
Apache 有一个父进程.此进程创建子进程来处理传入 Web 服务器的任何请求.Web 服务器启动时启动的初始子进程数量由 apache 配置中的
StartServers
指令配置.这个数字会随着访问 Web 服务器的请求数量的增加而增加,直到达到ServerLimit
.Apaches point of view
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 untilServerLimit
is reached.如果 PHP(作为 mod_php 运行,作为 CGI 在脚本执行结束时所有资源都被释放)现在被告知为请求建立与数据库的持久连接,即使在脚本完成后,该连接也会保持.现在保持的连接是处理请求的 apache 子进程和数据库服务器之间的连接,并且可以被这个确切的子进程正在处理的任何请求重用.
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.
如果由于某种原因(不要问我确切的原因),子进程被占用的时间比实际请求的时间长并且另一个请求进来,父 apache 进程将此请求重定向到一个(新)子进程,这可能到目前为止还没有建立到数据库的连接.如果在脚本执行期间必须这样做,它会像您观察到的那样引发 SID.现在有两个连接被apache的两个不同的子进程持有.
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.
重要的是要知道,这也会引起很多麻烦.如果在脚本执行过程中出现死循环或中止事务或其他一些甚至不可预测的错误,连接将被阻塞且无法重用.也可能发生数据库的所有可用连接都被使用,但 apache 服务器的另一个子进程试图访问数据库.该进程暂时被阻止,直到数据库或 apache 释放连接(超时或自愿终止).此页面上有关此主题的任何进一步信息:http://www.php.net/manual/en/features.persistent-connections.php
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. :)
我刚刚读完了这篇评论.它描述了我在上面总结的过程,并提供了有关如何优化 apache 服务器以更好地与持久连接一起工作的有用信息.不过,它可以在有或没有 oracle 数据库后端的情况下使用.你应该看看:http://www.oracle.com/technetwork/articles/coggeshall-persist-084844.html
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
相关文章