情况如下:
服务器 a 上的 php 脚本,由用户“web”(nginx + php-fpm)运行,应该通过 pdo 库访问服务器 b 上的 mysql,但得到 SQLSTATE[HY000] [2003] 无法连接到“xxx.xxx.xxx.xxx”上的 MySQL 服务器 (4)
服务器 a centos 6.5,php 5.3;服务器 b centos 6.2,mysql 5.1
但是,mysql 命令行客户端 - 以非特权用户身份运行 - 可以完美连接,可重复且稳定。
一旦 mysql 命令行客户端在服务器之间成功建立连接,php 脚本也会成功运行大约 5-7 分钟,大概直到 mysql 命令行客户端连接超时。
我错过了什么?
这是测试脚本:
<?php
try {
$dbh = new PDO('mysql:host=111.111.111.111;dbname=myname;port=3306', 'myuser',
'mypass');
echo 'Connected to database';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
答案1
所以事实证明这毕竟是一个路由问题。
我们目前正在使用静态路由网络,并且 mysql 服务器 a 没有定义回服务器 b 的路由。
网络设置有点混乱,因为物理连接如下:服务器 b(异地)> vpn gw > internet > checkpoint fw > openwrt 路由器 > 服务器 a
显然,mysql 命令行客户端更加宽容并且无论如何都能够建立该连接,但 pdo 库却不能。
添加路由之后,pdo库可以成功自行建立连接,并且运行顺利。
因此,请检查您的路由,即使 ping/telnet/mysql 连接看似正常。
顺便问一下,“中断系统调用”错误会涵盖这种情况吗?
答案2
$ perror 4
OS error code 4: Interrupted system call
当收到此特定错误时,您应该再试一次。
这可能预示着负载过重的服务器/网络。在这种情况下,你可以尝试增加连接超时作为短期解决方案,并长期解决拥堵问题。
答案3
刚刚遇到这种问题,虽然在服务器,地址等方面有点不同。帮助我解决这个问题的重要的事情是:
- 尝试从运行 PHP 的同一台机器上通过 CLI 访问相关数据库
- 尝试从不同的盒子通过 PHP 连接数据库
如果第一个失败而第二个成功,那么可能是因为您的数据库中有一个额外的用户帐户指定给您所连接主机。
使用以下方式检查现有用户
select host, user, password from mysql.user;
如果你发现类似这样的情况:
| host | user | password
+----------------+----------------+------------------------------------------
| 10.10.10.1 | myuser |
| % | myuser | *0803B925439C244BA857C3FD07A4F86A556F0925
这意味着您连接的 PHP 主机上附加了额外的用户。删除它或为该主机特定用户设置适当的密码和权限。