在 MySQL 中使用持久连接,但仍有许多打开的连接
Using persistent connections in MySQL but still many open connections
我有一个回调 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 |
(user
和 database
屏蔽实际用户和数据库)
我对持久连接有什么误解吗?我可以做些什么来避免类似的联系?
我猜这是连接池。在您的例子中,它创建了一个包含 4 个连接的池,可用于并行服务 4 requests/queries。如果您只有 1 个连接并且其中有一个查询 运行,那么任何其他需要数据库的请求都必须等待。
另一种解释可能是您的 Web 服务器是 运行 4 个子进程并行处理多个请求,因此每个子进程 creates/gets 它自己的连接可以在内部重用
这可以适用于许多其他 webserver/frameworks 而不是特定于 php/mysqli
持久连接可由后续请求重复使用,但如果您的站点正在处理多个并发 请求,则每个请求都需要自己的连接。
换句话说,多个并发PHP请求不能同时使用同一个数据库连接。
MySQL处理多个连接不是问题。在 MySQL 8.0 中,默认 max_connections
限制设置为 151,但如果您的服务器足够强大,它可以更高。在我的工作中,我们使用高端数据库服务器,因此我们将 max_connections
提高到 4096。但我们提醒开发人员,他们可能不希望它超过 1024。通常我们会看到连接数保持在几百.
是的,我相信你对持久连接有一点误解。
I've understood, this way mysqli finds an existing connection with same parameters or creates one if it doesn't exist, instead of opening a new connection every time
当您使用持久连接时,PHP 不会在 PHP 脚本结束执行时请求关闭连接。相反,连接将保持活动状态,如果处于空闲状态,PHP 可能会再次重用该连接。
无论如何,同一个脚本的每次执行都需要一个单独的连接。如果没有可重用的连接,则 PHP 将尝试打开一个新的持久连接。
这只会导致灾难。如果您没有正确地手动清理连接,您会看到一些奇怪的行为。如果您不需要使用它们,最好远离它们。使用持久连接只能使您更快地达到 max_connections
限制。
如果您在 localhost 上使用 MySQL(似乎是这种情况),您将看不到太多性能提升。没有理由进行如此小的优化。打开和关闭连接通常是一个非常快速的过程,尤其是在本地主机上。
一道教科书式的XY题
the database loading takes some time and I would like to speed up that process
我觉得持久连接将是解决您的问题的最后选择(如果有的话)。
As I've understood, this way mysqli finds an existing connection with same parameters or creates one if it doesn't exist, instead of opening a new connection every time
实际上远非如此。 PHP 中的持久连接绑定到 PHP 中执行的多个线程。碰巧打开连接的每个线程都会进一步保持它打开,为它正在运行的脚本提供这个已经打开的连接执行。持久连接是指持久的,或者换句话说,是持久打开的。
因此,您能看到的画面是意料之中的。
只要您不 运行 进入 "Too many connections" 错误就没问题,尽管我怀疑使用持久连接是否会带来可衡量的好处。
我有一个回调 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 |
(user
和 database
屏蔽实际用户和数据库)
我对持久连接有什么误解吗?我可以做些什么来避免类似的联系?
我猜这是连接池。在您的例子中,它创建了一个包含 4 个连接的池,可用于并行服务 4 requests/queries。如果您只有 1 个连接并且其中有一个查询 运行,那么任何其他需要数据库的请求都必须等待。
另一种解释可能是您的 Web 服务器是 运行 4 个子进程并行处理多个请求,因此每个子进程 creates/gets 它自己的连接可以在内部重用
这可以适用于许多其他 webserver/frameworks 而不是特定于 php/mysqli
持久连接可由后续请求重复使用,但如果您的站点正在处理多个并发 请求,则每个请求都需要自己的连接。
换句话说,多个并发PHP请求不能同时使用同一个数据库连接。
MySQL处理多个连接不是问题。在 MySQL 8.0 中,默认 max_connections
限制设置为 151,但如果您的服务器足够强大,它可以更高。在我的工作中,我们使用高端数据库服务器,因此我们将 max_connections
提高到 4096。但我们提醒开发人员,他们可能不希望它超过 1024。通常我们会看到连接数保持在几百.
是的,我相信你对持久连接有一点误解。
I've understood, this way mysqli finds an existing connection with same parameters or creates one if it doesn't exist, instead of opening a new connection every time
当您使用持久连接时,PHP 不会在 PHP 脚本结束执行时请求关闭连接。相反,连接将保持活动状态,如果处于空闲状态,PHP 可能会再次重用该连接。
无论如何,同一个脚本的每次执行都需要一个单独的连接。如果没有可重用的连接,则 PHP 将尝试打开一个新的持久连接。
这只会导致灾难。如果您没有正确地手动清理连接,您会看到一些奇怪的行为。如果您不需要使用它们,最好远离它们。使用持久连接只能使您更快地达到 max_connections
限制。
如果您在 localhost 上使用 MySQL(似乎是这种情况),您将看不到太多性能提升。没有理由进行如此小的优化。打开和关闭连接通常是一个非常快速的过程,尤其是在本地主机上。
一道教科书式的XY题
the database loading takes some time and I would like to speed up that process
我觉得持久连接将是解决您的问题的最后选择(如果有的话)。
As I've understood, this way mysqli finds an existing connection with same parameters or creates one if it doesn't exist, instead of opening a new connection every time
实际上远非如此。 PHP 中的持久连接绑定到 PHP 中执行的多个线程。碰巧打开连接的每个线程都会进一步保持它打开,为它正在运行的脚本提供这个已经打开的连接执行。持久连接是指持久的,或者换句话说,是持久打开的。
因此,您能看到的画面是意料之中的。
只要您不 运行 进入 "Too many connections" 错误就没问题,尽管我怀疑使用持久连接是否会带来可衡量的好处。