MySQLi PHP随机连接错误

7
我从php后端作业和php网页日志中随机收到以下错误。有一个应用程序服务器,其运行php后端任务和php web服务器。两者都连接到同一个数据库服务器。使用php mysqli面向对象库连接到数据库。在my.cnf中将最大连接数设置为750。并没有看到达到这么多连接。

PHP警告:mysqli :: mysqli():(HY000 / 2003):无法连接到“77.777.120.81”上的MySQL服务器(99)/ usr / local / dev / classes / Admin.php的第15行

无法连接到MySQL:无法连接到“77.777.120.81”上的MySQL服务器(99)


2
无法从中判断。这是一个网络或服务器问题,而不是您的脚本问题。也许防火墙上有速率限制? - Barmar
我认为我以前遇到过这个问题,我同意@Barmar的看法,这绝对是服务器问题。 您使用的是哪台服务器,并且能够通过该服务器访问mysql吗? - Naguib Ihab
1
你看过 https://dev59.com/EmTWa4cB1Zd3GeqPEpXy 吗? - Eugene
默认情况下,最大连接数为151;更改配置为750后,您是否重新启动了MySQL服务器?另外一些问题:“AWS上的所有服务器”:您是在使用RDS还是在EC2上托管MySQL?如果在EC2上,则MySQL是否在不同的EC2实例上?(如果不是,请使用“localhost”,如果是,则使用持久连接。) - Robbie
所以...你在php代码中连接和断开MySQL,对吗?如果是的话-不要那样做。利用FCGI的强大功能,让持久连接为你工作。在真实世界的情况下,对MySQL进行超过几个连接就没有意义了,特别是如果您只有一台服务器来执行所有这些操作。 - N.B.
显示剩余4条评论
2个回答

6
正如这篇Percona数据库性能博客文章中所描述的那样,您的问题是应用程序无法打开另一个到MySQL服务器的连接。您的本地TCP端口已经用尽。作为解决方案,我建议调整TCP参数设置。
  • tcp_tw_reuse(布尔值;默认值:禁用;自Linux 2.4.19 / 2.6) 允许在从协议视点安全时重用TIME_WAIT套接字以进行新连接。请勿更改此选项,除非有技术专家的建议/请求。

通过将/proc/sys/net/ipv4/tcp_tw_reuse设置为1,可以强制内核重用处于TIME_WAIT状态的连接。实际上会发生什么是,您将继续看到挂起在TIME_WAIT中的关闭连接,直到它们过期或请求新连接。对于后一种情况,连接将被“恢复”。

  • tcp_tw_recycle(布尔值;默认值:禁用;自Linux 2.4) 启用快速回收TIME_WAIT套接字。不建议启用此选项,因为在使用NAT(网络地址转换)时会引起问题。

    启用/proc/sys/net/ipv4/tcp_tw_recycle后,关闭的连接将不再显示在TIME_WAIT下-它们完全从netstat中消失。但是,只要您在60秒内打开一个新连接,它就会回收其中的一个。但是,每个写有关此替代方案的人似乎都建议不使用它。底线是:最好重用连接而不是回收它。

  • tcp_max_tw_buckets (整数; 默认值: 见下文; 自Linux 2.4起) 该参数指定系统中允许保持TIME_WAIT状态的套接字数量上限,此上限仅用于防止简单的拒绝服务攻击。默认值为NR_FILE * 2,具体取决于系统内存情况。如果超过此数量,则套接字将被关闭并打印警告信息。

    该参数规定了同时可以保持在TIME_WAIT状态的连接数量:当连接数量超过这个限制时,内核会直接关闭处于TIME_WAIT状态的连接。例如,在一个仅由6个端口组成的TCP端口范围的服务器场景中,如果/proc/sys/net/ipv4/tcp_max_tw_buckets设置为5,则打开6个与MySQL的并发连接,并立即关闭所有6个连接,你会发现只有5个连接处于TIME_WAIT状态。与tcp_tw_recycle一样,其中一个连接将从netstat输出中消失。这种情况允许立即打开新连接,而不需要等待一分钟*

    • 在连接数据库服务器方面,许多应用程序选择仅针对单个请求打开一个新连接,并在处理完请求后立即关闭该连接。尽管连接是由客户端(应用程序)关闭的,但它使用的本地端口不会立即被操作系统释放以便另一个连接重复使用:它将在TIME_WAIT状态下保持(通常为)60秒——这个值不容易更改,因为它是硬编码在内核中的。

    但是,在其他5个处于TIME_WAIT状态的连接之一过期并释放它所使用的本地端口之前,第二个连接将无法打开。因此,秘密在于在可用网络端口数量和允许保持在TIME_WAIT状态的连接数量之间找到折衷。该设置的默认值为65536,这意味着默认情况下当所有连接关闭时,系统允许所有可能的连接进入TIME_WAIT状态。


  • 感谢您的时间和信息。当我执行 netstat 命令时,我能够发现在 mysql 端口 3306 上有 25044 个 TIME_WAIT,所有端口上的 TIME_WAIT 总数为 30044。当我检查 /proc/sys/net/ipv4/tcp_max_tw_buckets 的值时,它的值为 32768。我应该使用回收设置还是需要减少 tcp_fin_timeout 值? - Arav
    @Arav 我认为tcp_tw_reuse选项是最好的。 - user2560539
    谢谢,我会尝试tcp_tw_reuse选项。 - Arav

    1

    感谢您的时间和信息。当我执行netstat时,能够发现在mysql端口3306上有25044个处于TIME_WAIT状态,并且所有端口的TIME_WAIT总数为30044。当我检查/proc/sys/net/ipv4/tcp_max_tw_buckets的值时,它的值为32768。这是循环设置是否足够,还是需要减少tcp_fin_timeout? - Arav
    tcp_tw_reuse. 我已经更新了答案并添加了一个参考,描述哪种解决方案更好。 - Jordan Enev
    谢谢,我会尝试使用tcp_tw_reuse。 - Arav

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接