php 完全理解 PDO ATTR_PERSISTENT

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23432948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 16:43:30  来源:igfitidea点击:

Fully Understanding PDO ATTR_PERSISTENT

phporaclepdooracle10g

提问by MonkeyZeus

Question:

题:

What are the rules/logic behind persistent connection management when using PDO?

使用 PDO 时,持久连接管理背后的规则/逻辑是什么?



Environment:

环境:

Web Server

网络服务器

  • Windows 7 x64
  • Dual-core with 16GB RAM
  • Apache 2.2.17
  • PHP 5.3.5
  • Connecting through DSN string with IP address, port, service name, etc...
  • No ODBC for DB conn (been trying to create one for 2 hours now, thanks Oracle!)
  • 视窗 7 x64
  • 双核 16GB RAM
  • 阿帕奇 2.2.17
  • PHP 5.3.5
  • 通过带有 IP 地址、端口、服务名称等的 DSN 字符串连接...
  • 没有用于 DB conn 的 ODBC(现在已经尝试创建一个 2 小时了,感谢 Oracle!)

DB Server

数据库服务器

  • Oracle 10g on Linux
  • Multi-core with 4GB RAM
  • Username specifically created for my web app (yes, it's fake)
    • user: webuser
  • Linux 上的 Oracle 10g
  • 多核 4GB RAM
  • 专门为我的网络应用创建的用户名(是的,它是假的)
    • 用户:网络用户


My understanding/observations:

我的理解/观察:

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?

?>
  • Script reliably takes about ~.09 seconds to execute with framework overhead, etc...
  • 脚本在框架开销等情况下可靠地执行大约需要大约 .09 秒...

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

?>
  • Script takes ~.12 seconds to execute upon initial visit with framework overhead, etc...
  • Sub-sequent executes take ~.04
  • 脚本在初始访问时需要约 .12 秒才能执行,并带有框架开销等...
  • 后续执行 take ~.04


The issue:

问题:

I visit the page and webusergets a SID=1

我访问该页面并webuser获得SID=1

My colleague visits the page and webusergets an additional SID=2<- rinse, repeat, and increment SID for new computers visiting this page

我的同事访问该页面并webuser获得额外的SID=2<- 为访问此页面的新计算机冲洗、重复和增加 SID

Shouldn't a new visitor be re-using SID=1?

新访客不应该重新使用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-persistentblogs.

我已经使用 RTFM 一段时间了,而谷歌搜索只产生了微薄的Advantages of Persistent vs. Non-persistent博客。

回答by func0der

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 StartServersdirective in the apache configuration. The number goes up as needed with a raising amount of requests hitting the web server until ServerLimitis reached.

Apache 有一个父进程。此进程创建子进程来处理传入 Web 服务器的任何请求。Web 服务器启动时启动的初始子进程数量由StartServersapache 配置中的指令配置。随着访问 Web 服务器的请求数量的增加,该数字会根据需要增加,直到ServerLimit达到。

PHP and persistent connections

PHP 和持久连接

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.

如果 PHP(作为 mod_php 运行,作为 CGI 在脚本执行结束时所有资源都被释放)现在被告知为请求建立与数据库的持久连接,即使在脚本完成后,该连接也会保持。现在保持的连接是处理请求的 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 进程将此请求重定向到可能尚未建立的(新)子进程到此时为止的数据库连接。如果在脚本执行期间必须这样做,它会像您观察到的那样引发 SID。现在有两个连接由 apache 的两个不同子进程持有。

Keep in mind that...

请记住,...

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

重要的是要知道,这也会引起很多麻烦。如果在脚本执行过程中出现死循环或中止事务或其他一些甚至不可预测的错误,连接将被阻塞且无法重用。也可能发生数据库的所有可用连接都被使用,但 apache 服务器的另一个子进程试图访问数据库。该进程暂时被阻止,直到数据库或 apache 释放连接(超时或自愿终止)。此页面上有关此主题的任何进一步信息: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

我刚刚读完中提到的文章@MonkeyZeus此评论。它描述了我上面总结的过程,并提供了有关如何优化 apache 服务器以更好地与持久连接一起工作的有用信息。不过,它可以在有或没有 oracle 数据库后端的情况下使用。你应该看看:http: //www.oracle.com/technetwork/articles/coggeshall-persist-084844.html

回答by Amir Fo

Advantages

好处

From the manual page of phpfor persistent connections on this link:

这个链接php上的持久连接的手册页:

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.

持久连接是在脚本执行结束时不会关闭的链接。当请求持久连接时,PHP 会检查是否已经存在相同的持久连接(从之前保持打开状态) - 如果存在,则使用它。如果它不存在,它会创建链接。

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.

使用持久连接的原因当然是减少了相当昂贵的连接数量;尽管它们使用 MySQL 比使用大多数其他数据库要快得多。

Issues

问题

There are some issues with table lockingwhile 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.

如果脚本由于某种原因无法释放锁,那么使用相同连接的后续脚本将无限期阻塞,并且可能需要您重新启动 httpd 服务器或数据库服务器。

Another is that when using transactions by mysql commit.

另一个是通过 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.

如果脚本执行在事务块之前结束,事务块也将转移到下一个使用该连接的脚本。在任何一种情况下,您都可以使用 register_shutdown_function() 注册一个简单的清理函数来解锁您的表或回滚您的事务。

I suggest you read this questionabout disatvantages of persistent connections.

我建议您阅读有关持久连接的缺点的问题

回答by BrainInBlack

PDO is kinda funny that way. Even the same user/visitor can cause a second or even third instance to be created. The same thing happened to me on my local machine, while testing the performance of my db queries.

这样 PDO 有点好笑。即使是同一个用户/访问者也可能导致创建第二个甚至第三个实例。同样的事情发生在我的本地机器上,同时测试我的数据库查询的性能。

That is nothing to worry about, because these instances will timeout sooner or later, the exact timeout depends on your server configuration.

这没什么好担心的,因为这些实例迟早会超时,确切的超时取决于您的服务器配置。

Why that happens? If the current instance is busy, then a new instance will be created and the older one will timeout sooner or later. At least that seems logical to me.

为什么会这样?如果当前实例繁忙,则将创建一个新实例,而旧实例迟早会超时。至少在我看来这很合乎逻辑。