间歇性 MySQL 连接错误

间歇性 MySQL 连接错误

我最近在我的服务器上收到这些错误:

mysql_connect() [function.mysql-connect ]: 
   Can't connect to MySQL server on 'xxx.xxx.xxx.xxx' (4)

我不认为这是一个凭证问题,因为用户名、密码、主机 IP 和数据库名称都是从平面文件配置中读取并存储在 PHP 常量中。另外,我的错误日志告诉我,所使用的凭证实际上是配置中的凭证。

我试着用谷歌搜索一下,有人指出了一个max_connections问题。这个网站仍处于测试阶段,并发用户数不超过 10。我查了一下 的值,max_connections它是 2048

MySQL 版本为 5.0.91,服务器为 Gentoo Linux(如其名称所示version_comment)。套接字文件位于/var/run/mysqld/mysqld.sock,端口位于3306

真正让我烦恼的是,这个错误似乎是间歇性的。当我试图重现它时,我真的无法捕捉到它。有人在一个网站上说,错误索引(4)意味着中断的系统调用。

这是否意味着我可以将错误视为我的网络主机的错误而不是我的 PHP 脚本的错误?

答案1

尝试查看您是否没有超出最大打开文件限制,dmesg并观察“打开文件过多”错误。

如果超出该限制,则必须通过/etc/security/limits.conf以下语句进行更改来增加系统固定的限制:


mysql           soft    nofile          2048
mysql           hard    nofile          4096

其中 2048 和 4096 是用户“mysql”可以打开的最大文件数。(这包括所有文件描述符,例如套接字)

答案2

如果您的连接字符串引用了服务器节点名称并需要 DNS,请确保它不是导致连接尝试超时的中间缓慢 DNS 解析。如果合适,请使用 localhost。如果合适,运行本地 DNS。如果合适,在 LMHOSTS 文件中短路。完全消除对 DNS 的需求,如果合适,请指定 IP 地址。无论如何,不​​要依赖于连接字符串中外部有时很慢的 DNS 服务器名称查找。

有时连接字符串没有问题;有时 DNS 解析会间歇性地太慢。这可能是间歇性连接问题的原因之一。

示例:假设您有一个托管 mysql 和 apache 的云实例,但有时您在本地 devo 机器上运行站点。因此,在您的连接字符串中,您使用完整的服务器节点名称,因此站点可以从部署站点或您的 devo 机器“工作”。可能在您的 devo 机器上永远不会失败(因为您的 devo 机器 DNS 始终正常),但您在部署的站点上会遇到间歇性连接问题(因为即使 mysql 实例位于同一位置,您的连接字符串仍然需要 DNS 解析回自身,但您的云实例上的 DNS 有时并不那么正常。有点令人抓狂,因为在部署的实例中,mysql 实例实际上是本地的。但实际上甚至不是重点——重点是,您的 devo 机器 DNS 响应时间在所有负载条件下与云实例上的响应时间之间的差异。因此,在云实例上尽可能简单。错误不会是“DNS 太慢”,即使这是根本原因。

答案3

您可以通过利用mysql_error()mysql_errno()-功能,但据我所知,你的假设是正确的。

作为一个简短的错误修复(我通常在我的 web 应用程序中实现)是在两秒后重新连接并进行日志记录:

$i = 0;
if ($i < 3 && ($db = mysql_connect(...)) == false) {
    trigger_error('Could not connect to ...', E_USER_WARNING);
    $i++;
    sleep(2);
}
if (!$db)
    die('Could not connect to ... for 3 times with a 2 second dely - giving up');

由于网站流量较低,您可以考虑运行tcpdump在服务器上创建一个文件,并配置你的 php 脚本,以便在连接失败时向你发送警告。将 tcpdump 文件复制到本地,然后通过以下方式分析连接失败wireshark

您还应该检查 mysql-daemon 日志和故障发生时系统上的系统日志是否存在异常。

请注意,记录您的流量将记录流量的所有内容,包括密码和其他敏感信息,因此可能违反公司政策或法律。您应该在停用日志记录后擦除 tcpdump 文件,以免在服务器上留下任何敏感信息,并通过 ssh 或任何其他适当的加密连接传输文件。

相关内容