令人困惑的PDO问题:无法通过套接字连接/访问被拒绝/无法连接到服务器(共享主机)

16

问题已经发生了变化,为了避免像之前那样因为别人修改问题而导致差评,我会在下面保留原始问题:

我正在使用一个(非常糟糕的)共享主机,该主机安装了PDO,但它无法正常工作。 使用默认参数。

<?php
try {
    $dbh = new PDO('mysql:host=localhost;dbname=THE_DB_NAME', 'THE_USER', 'THE_PASSWORD');
    echo 'Connected to database';
    }
catch(PDOException $e)
    {
    echo $e->getMessage();
    }
?>

它会抛出这个消息:

SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

使用简单的mysql_connect函数即可正常运行。

套接字路径似乎正确(phpinfo和此查询都显示):

show variables like 'socket';

请确认。

本地主机重定向到10.103.0.14(这个数据来自mysql_get_host_info()和phpMyAdmin)

在PDO中,如果我将localhost替换为127.0.0.1,我将得到:

SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (111) 

如果我将localhost替换为10.103.0.14:

Access denied for user 'USER_NAME'@'10.103.0.14' (using password: YES

两个IP地址(127.0.0.1和10.103.0.14)都可以与mysql_connect一起使用。

因此,问题显然来自PDO连接。

有人知道这可能来自哪里,或/和任何修复的方法吗?

一些服务器数据:

PHP版本:5.2.10 您可以查看服务器的phpinfo:http://web.lerelaisinternet.com/abcd.php?v=5 没有命令行可用。 (我知道这应该是技术支持的工作,但他们非常慢)

谢谢

之前的问题:

如何在共享主机上找到mysql.sock(需要棘手的方法...)

所以今天的问题是:PDO连接在共享主机上不起作用,但它应该可以(已安装在服务器上)。 只是一个基本的PDO连接:

<?php
try {
    $dbh = new PDO('mysql:host=localhost;dbname=THE_DB_NAME', 'THE_USER', 'THE_PASSWORD');
    echo 'Connected to database';
    }
catch(PDOException $e)
    {
    echo $e->getMessage();
    }
?>

抛出此消息:
SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

一个普通的mysql连接:

mysql_connect("localhost", "THE_USER", "THE_PWD") or die(mysql_error()); 
mysql_select_db("24DLJLRR1") or die(mysql_error());;
echo 'Connected to database <br/>';

运行正常。

显然它找不到.sock文件。 我认为指定正确的地址应该可以解决问题,我尝试了一些在互联网上找到的“经典”mysql路径,但没有成功。 phpinfo显示它位于这个地址(/var/lib/mysql/mysql.sock) (PHP版本为5.2.10) 您可以查看服务器的phpinfo:http://web.lerelaisinternet.com/abcd.php?v=5

所以我正在努力找出它在哪里!!! 我试图在phpMyAdmin界面中寻找信息,但我找不到信息,而且似乎phpMyAdmin连接到不同的服务器(它具有不同的IP地址,并尝试使用php连接到它会出现“密码错误”的错误)。 mysql_connect也连接到此地址,我认为它会重定向到具有某些内部密码/登录的不同服务器。

如果您有任何关于如何获取此信息的想法(提供商的技术支持正在“修复问题”...已经过去1个月了...)。 另外,也许问题来自其他地方,但是在其他共享主机上相同的东西可以正常工作...

需要PDO是因为我在这个网站上使用Symfony框架和Doctrine,而Doctrine插件需要PDO...我不想从头开始重新制作网站!

感谢您的帮助!


2
可能是套接字存在,但您没有访问它所需的必要权限。不管怎样,这不是您提供商技术支持的问题吗? - Pekka
我猜这是他们的工作!他们太菜了,我们已经等了一个多月,而且还在法国,需要30分钟才能找到正确的人。问题是这是一个重要的客户,我们必须发货...(网站现在正在使用镜像运行,但客户希望它在他的主机上,并且属于法国电信公司,所以我们不能说它很菜)。 此外,我们无法直接与服务器技术支持交谈。 那么为什么我没有访问权限呢?我的意思是,如果PDO已安装并且我可以通过mysql_connect连接,我应该有这些权限,不是吗? - Julien
就我了解的情况,看来你运气不太好。本地主机映射到了不同的IP地址。但是似乎MySQL服务器本身只允许来自本地主机(在他们的情况下解析为您的10.103.0.14)的访问。如果主机是本地主机,PDO似乎使用套接字连接。(请参阅php.net文档,PDO - 连接第二个注释)但是为什么mysql_connect可以使用127.0.0.1却能正常工作,这非常奇怪。在这种情况下,使用host=127.0.0.1连接PDO也应该可以工作。 - Rufinus
14个回答

22

这个问题已经被标记为已解答,但实际上并未真正解决(没有更改数据库)。 因此,以防其他人也遇到了这个问题...

最简单的解决方法是首先获取套接字路径(可以通过查看php.ini文件或使用:phpmyadmin或控制台(或在mysql或mysqli中构建)来获取)

然后运行以下查询(除PDO之外的任何内容):

show variables like 'socket';       //as mentioned by symcbean

然后,在PDO连接字符串中,将其更改为使用套接字而不是主机名:

$dbc = new PDO("mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=$DBName", $User, $Password, array(PDO::ATTR_PERSISTENT => true)); // 使用持久连接

这对我有用。


15

FWIW,我曾遇到此问题并将我的主机从“localhost”更改为“127.0.0.1”。

我不知道为什么本地主机(localhost)无法工作,但这个方法起作用了。

奇怪的是,我们有很多服务器,几乎每个都使用本地主机名(localhost)可以正常工作。


我也是。如果你弄清楚为什么,请在gplus.to/swader上给我留言。我的hosts文件已设置将127.0.0.1定向到localhost,所以没问题。很奇怪。 - Swader
我在服务器上看到了相同的错误,此时有第二个mysql-server处于活动状态(ps aux | grep mysql)...通过“127.0.0.1”连接仍然可以工作,但是通过“localhost”(unix-socket)无法工作:“无法通过套接字连接到本地MySQL服务器…” -> 我们不得不“kill -9”并重新启动mysql :/ - Lars Moelleken

7

您的服务器是否启用了SeLinux(强制执行)?如果是,请尝试以root身份运行:

# setsebool -P httpd_can_network_connect on

4

我遇到了一个问题,生产版本运行良好,但测试版本无法连接PDO :/ 两个版本都位于同一服务器上,测试版本在子目录中。

解决方法是将DSN中的localhost替换为IP地址。

'mysql:host=localhost;dbname=db'

成为
'mysql:host=127.0.0.1;dbname=db'

是的,已经修复了,但为什么?Ping localhost 告诉我 IP 是 127.0.0.1,那么为什么不能使用 localhost? - RyanNerd
机器上的主机解析似乎有些问题。 - Valentin Rusk

4

使用可用的连接,运行查询:

show variables like 'socket';

(这与select语句的行为完全相同)...然后你会得到运行socket的路径。

接着检查文件权限。


非常感谢!现在的问题是我得到了:Array([0]=>socket [1]=>/var/lib/mysql/mysql.sock),所以套接字确实在正确的位置......我想我要自杀了。我应该如何检查文件权限?(如果它与mysql_connect一起工作,则应该具有)也许这只是他们PDO安装的问题... - Julien
我认为mysql_connect连接没有使用套接字,这就是为什么它能够工作的原因。只是为了好玩,如果在工作的mysql连接中将localhost替换为127.0.0.1,会发生什么? - Pekka
这很奇怪。我认为PDO使用的客户端库与经典的mysql_connect()不同,但这里有一些不同的问题...我不知道这可能是什么。 - Pekka
是的。你可能真的需要更换服务提供商或者加大对支持人员的压力:( - Pekka
要查找权限,根据服务器的配置,您可以只需使用 ls -l $socket 或 print_r(stat($socket))(并解码数字)。 - symcbean
显示剩余2条评论

4

你可以尝试使用服务器名为127.0.0.1而不是localhost吗?

如果我没记错的话,对于一些MySQL的驱动程序/适配器来说,这决定了是否使用socket来建立连接。


我得到了一个不同的错误: SQLSTATE[HY000] [2003] 无法连接到 '127.0.0.1' 上的 MySQL 服务器(111) - Julien
本地主机上是否有运行中的mySQL服务器?你确定吗? - Pekka
啊,抱歉,你之前说过有。 - Pekka
有点令人困惑,因为 mysql_get_host_info() 函数给了我一个 IP 地址(10.103.0.14),而不是 10.0.0.127。 如果我尝试使用这个 IP 地址从 PDO 连接,我会得到以下错误信息: Access denied for user 'USER_NAME'@'10.103.0.14' (using password: YES)。 - Julien
我已经开始有这样的感觉,即您的提供者正在将“localhost”映射到不同的IP地址(虽然还不确定)。您能否尝试一下symcbean答案中的评论? - Pekka
这个评论帮了我很多,节省了我好几个小时的时间。谢谢Pekka! :) - Mike

2

尝试:

exec('`which mysql_config` --socket');

这应该会展示你配置的套接字。


如果他能运行外部程序,这是个好主意。也许可以使用 find 命令查找任何 mysql.sock 文件。 - Pekka
好像我不能执行 警告:由于安全原因,exec()已被禁用 谢谢想法 :) - Julien

1
我发现这个页面后,想说一句话。我遇到了完全相同的问题。我的服务器上只安装了Apache和PHP,而MySQL安装在另一台机器上。我尝试使用服务器的DNS名称和IP地址,并确认可以ping通。同一台机器上的PHP应用程序可以正常连接数据库,使用旧语法mysql_connect()。但是从CLI连接PDO时会抛出此错误。
对我来说解决方案是检查我的DSN。DSN本身的任何拼写错误都会被静默地忽略,PDO会假定你的意思是localhost。我的问题是在DSN中将"name="写成了"dbname="。

1
我找到了奇怪行为的原因。如果bind-address与127.0.0.1或0.0.0.0(所有地址)不同,PDO无法连接到127.0.0.1。

0

我的问题可能与 OP(原帖)不同,但我认为值得发布。我在虚拟机上进行了软件升级,然后重新启动,出现了 OP 的错误信息。结果是一个内存不足的问题阻止了 MySQL 的启动。删除一些大文件解决了问题。


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