在 MySQL 中使用持久连接但仍有许多打开的连接

Posted

技术标签:

【中文标题】在 MySQL 中使用持久连接但仍有许多打开的连接【英文标题】:Using persistent connections in MySQL but still many open connections 【发布时间】:2020-03-29 17:09:53 【问题描述】:

我有一个在回调 api 上工作的聊天机器人,每次有人写消息时它都会在我的服务器上发送一个请求

最近,我读到了所谓的持久连接,这让我觉得我可以避免每次在我的服务器上收到请求时重新连接到数据库,因为数据库加载需要一些时间,我想加快速度那个过程

所以,我已将脚本中的任何连接更改为具有 p: 前缀,就像这样

$conn = new mysqli("p:".$servername, $username, $password, $dbname);

据我了解,这样 mysqli 会找到一个具有相同参数的现有连接,或者如果它不存在则创建一个,而不是每次都打开一个新连接

但是,几个小时后,我检查了打开的连接,我注意到一堆类似的连接,只是它们的ID 不同,就像这样

  ID      | USER | HOST      | DB       | COMMAND | TIME | STATE | INFO |
+---------+------+-----------+----------+---------+------+-------+------+
| 5248403 | user | localhost | database | Sleep   |   24 |       | NULL |
| 5248609 | user | localhost | database | Sleep   |  113 |       | NULL |
| 5247822 | user | localhost | database | Sleep   |    1 |       | NULL |
| 5248652 | user | localhost | database | Sleep   |   79 |       | NULL |

(使用userdatabase 屏蔽实际用户和数据库)


我对持久连接有什么误解吗?我可以做些什么来避免类似的连接?

【问题讨论】:

【参考方案1】:

后续请求可以重用持久连接,但如果您的网站正在处理多个并发请求,它们每个都需要自己的连接。

也就是说,多个并发的php请求不能同时使用同一个数据库连接。

MySQL 处理多个连接不是问题。默认的max_connections 限制在 MySQL 8.0 中设置为 151,但如果您的服务器足够强大,它可以更高。在我的工作中,我们使用高端数据库服务器,因此我们将max_connections 提高到 4096。但我们提醒开发人员,他们可能不希望它超过 1024。通常我们看到连接数保持在几百.

【讨论】:

【参考方案2】:

教科书式的 XY 问题

数据库加载需要一些时间,我想加快这个过程

我有一种感觉,如果有的话,持久连接将是解决您的问题的最后选择。

据我了解,这样mysqli会找到一个具有相同参数的现有连接,或者如果它不存在则创建一个,而不是每次都打开一个新连接

实际上远非如此。 PHP 中的持久连接绑定到 PHP 执行的多个线程。碰巧打开连接的每个线程都会进一步保持打开状态,为要执行的脚本提供这个已经打开的连接。意味着持久连接是持久的,或者换句话说,是持久打开的。

因此,您可以看到的图片是预期的。

只要您没有遇到“连接太多”错误就可以了,尽管我怀疑使用持久连接是否有明显的好处。

【讨论】:

【参考方案3】:

我猜这是连接池。在您的情况下,它会创建一个包含 4 个连接的池,可用于并行服务 4 个请求/查询。如果您只有 1 个连接并且正在其上运行查询,则需要数据库的任何其他请求都必须等待。

另一种解释可能是您的 Web 服务器正在运行 4 个子进程以并行处理多个请求,因此每个子进程创建/获取它自己的连接,它可以在内部重用

这可以用于许多其他网络服务器/框架,并没有特定于 php/mysqli

【讨论】:

我认为这与任何连接池无关。这不是 PHP 和 mysqli 的工作方式。恐怕你所描述的在 mysqli 中是不可能的。【参考方案4】:

是的,我相信你误解了持久连接是什么。

我明白了,这样mysqli会找到一个具有相同参数的现有连接,或者如果它不存在就创建一个,而不是每次都打开一个新连接

当您使用持久连接时,当 PHP 脚本结束执行时,PHP 不会请求关闭连接。相反,连接将保持活动状态,如果处于空闲状态,PHP 可能会再次重用该连接。

无论如何,同一脚本的每次执行都需要单独的连接。如果没有可重用的连接,那么 PHP 将尝试打开一个新的持久连接。

这只是灾难的秘诀。如果您没有正确手动清理连接,您会看到一些奇怪的行为。如果您不需要使用它们,最好远离它们。使用持久连接只能使您更快地达到max_connections 限制。

如果您在 localhost 上使用 MySQL(似乎是这种情况),您将不会看到太多的性能提升。几乎没有理由进行如此小的优化。打开和关闭连接通常是一个非常快速的过程,尤其是在本地主机上时。

【讨论】:

以上是关于在 MySQL 中使用持久连接但仍有许多打开的连接的主要内容,如果未能解决你的问题,请参考以下文章

php使用mysqli连接Mysql,怎么使用永久连接

在mysql中使用持久连接的目的和好处是啥?

持久数据库连接 - 是或否?

如何将MySql设置成持久性连接

防止来自 RStudio 的持久数据库连接

PHP 连接数据库啥情况下才会用到持久链接 mysql