简体   繁体   English

缓慢的 PHP 脚本导致 MySQL 服务器休眠(使用 pconnect())

[英]Slow PHP scripts cause MySQL server to sleep (using pconnect())

I'm having a problem with MySQL going to sleep because a PHP script takes too long.. then the mysql server is unresponsive until its done with that sleep process.我遇到了 MySQL 进入睡眠的问题,因为 PHP 脚本花费的时间太长......然后 mysql 服务器在完成该睡眠过程之前没有响应。 It then takes a minute to do any type of database request (faster if you remove the SLEEP process).然后,执行任何类型的数据库请求都需要一分钟(如果您删除 SLEEP 进程,则速度会更快)。

I use pconnect() to connect to the server, and I was told this might be causing the problem.我使用pconnect()连接到服务器,有人告诉我这可能会导致问题。 Is that right, and if so, why would a persistent connection just stop working like this?是这样吗,如果是这样,为什么持久连接会停止像这样工作?

Persistent connections can leave 'garbage' behind if the previous user of the connection aborted abnormally.如果连接的前一个用户异常中止,持久连接可能会留下“垃圾”。 Consider the case where you're doing a transaction with a series of individual queries.考虑一下您正在使用一系列单独的查询进行事务处理的情况。 Half-way through, let's assume the remote user killed the connection, which causes the script to abort.中途,让我们假设远程用户终止了连接,这导致脚本中止。 Because the mysql connection is persistent, it will not be closed when the script exits, and leaves the transaction open.因为 mysql 连接是持久的,所以脚本退出时它不会关闭,而让事务保持打开状态。

MySQL has no way of knowing it should do a roll-back, so it sits there with the transaction in play, waiting for another query to come in. MySQL 无法知道它应该进行回滚,因此它坐在那里处理事务,等待另一个查询进入。

When this connection gets re-used by another script, that script also has no way of knowing that a transaction is in play, and will simply start issuing its own queries.当此连接被另一个脚本重用时,该脚本也无法知道事务正在运行,并且只会开始发出自己的查询。

This can quite easily cause deadlocks, because of all these 'stale' transactions being left partially copmleted.这很容易导致死锁,因为所有这些“陈旧”事务都被部分完成。 If your scripts change any server-side settings for some reason, those settings will also be persisted on a per-connection basis, etc...如果您的脚本出于某种原因更改了任何服务器端设置,这些设置也将在每个连接的基础上保留,等等......

In other words, unless you're EXTREMELY careful with your code, persistent connections will cause a long series of strange behaviors that are very difficult to diagnose, because each connection will be in a different state for every script that uses them.换句话说,除非您对代码非常小心,否则持久连接将导致一系列非常难以诊断的奇怪行为,因为对于每个使用它们的脚本,每个连接都将位于不同的 state 中。

The persistent connection is held open while doing nothing.持久连接在什么都不做的情况下保持打开状态。 If it is set with a short timeout, it will go into sleep state and need to be woken again to be used.如果设置了短超时,它将 go 进入睡眠 state 并且需要再次唤醒才能使用。

It's very rare to actually require persistent connections, and the time saved by not reopening a connection to the MySQL server in your script seems to be wasted on the sleep/wake process.实际上需要持久连接是非常罕见的,并且通过不在脚本中重新打开与 MySQL 服务器的连接所节省的时间似乎浪费在睡眠/唤醒过程上。 I would advise you switch to plain old mysql_connect() .我建议您切换到普通的旧mysql_connect() If necessary, you can close your database connection and reestablish it later in the script.如有必要,您可以关闭数据库连接并稍后在脚本中重新建立它。

If your web server and database server are on the same machine there is virtually no savings with a persistent connection.如果您的 web 服务器和数据库服务器在同一台机器上,那么持久连接几乎不会节省任何费用。 And according to comments in PHP docs (I know they're not the best resource) Apache misbehaves with mysql_pconnect()根据 PHP 文档中的评论(我知道它们不是最好的资源) Apache 与mysql_pconnect()行为不端

  • Apache does not work well with persistent connections. Apache 不适用于持久连接。 When it receives a request from a new client, instead of using one of the available children which already has a persistent connection open, it tends to spawn a new child, which must then open a new database connection.当它接收到来自新客户端的请求时,它不会使用已经打开持久连接的可用子节点之一,而是倾向于生成一个新的子节点,然后它必须打开一个新的数据库连接。 This causes excess processes which are just sleeping, wasting resources, and causing errors when you reach your maximum connections, plus it defeats any benefit of persistent connections.当您达到最大连接数时,这会导致过多的进程处于休眠状态、浪费资源并导致错误,而且它会破坏持久连接的任何好处。 (See comments below on 03-Feb-2004, and the footnote at http://devzone.zend.com/node/view/id/686#fn1 ) (请参阅下面 2004 年 2 月 3 日的评论,以及http://devzone.zend.com/node/view/id/686#fn1的脚注)

See here for more info.请参阅此处了解更多信息。

The problem is that the persistent connections you're opening with mysql_pconnect are timing out on the MySQL side before they're timing out on the PHP side, causing PHP to try to use zombie connections.问题是您使用 mysql_pconnect 打开的持久连接在 PHP 端超时之前在 MySQL 端超时,导致 PHP 端尝试使用僵尸连接。 You need to make sure that the timeout is longer on the MySQL side than it is on the PHP side to prevent this from happening.您需要确保 MySQL 端的超时时间比 PHP 端的超时时间长,以防止这种情况发生。

This page also claims you can use mysql_ping() to work around this issue:该页面还声称您可以使用 mysql_ping() 来解决此问题:

http://www.php.net/manual/en/function.preg-match.php http://www.php.net/manual/en/function.preg-match.php

You can also just switch to mysql_connect if the performance is fine.如果性能良好,您也可以切换到 mysql_connect。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM