在Windows平台上,mysql_connect(localhost/127.0.0.1)连接速度较慢。

23
我正在使用Windows 7,Apache 2,PHP 5和MySQL 5,它们都在同一台机器上。 我发现了一个有趣的问题,我有以下代码:
    $sql = "select * from user1";
    $conn = mysql_connect("localhost", "root", "xxxxxxxx");
    mysql_select_db("test1");
    mysql_query("set names utf8");
    $result = mysql_query($sql, $conn);
    while ($row = mysql_fetch_assoc($result)){
        foreach ($row as $key => $value){
            echo $key." => ".$value." || ";
        }
        echo "<br/>";
    }
    mysql_free_result($result);
    mysql_close($conn);

以上代码的运行时间超过了1秒。

当我使用127.0.0.1代替localhost时,运行时间约为10毫秒。

我尝试在互联网上找到根本原因,结果如下:

我最近将我的开发环境从XP迁移到Windows 7并发现我开发的网页需要花费5秒钟才能加载完。这是不可接受的,所以我不得不追踪问题。 我最终追踪到有问题的函数/方法pdo::construct。我还发现mysql_connect连接需要大约1秒钟的时间。经过一些搜索,我找到了一个解释:php存在IPv6问题,您可以通过禁用IPv6或在进行连接时切换到IP地址127.0.0.1来解决此问题。

我想知道PHP中IPv6问题的原因,只是想更深入地了解一下。谢谢。


你的mysql服务器是否在::1上运行?如果不是,php将尝试通过ipv6连接,如果失败,它将回退到ipv4。这可能需要更长的时间。 - konqi
1
抱歉,我不明白“您的mysql服务器是否在::1上运行?”这句话的意思是什么?这是否意味着在同一台机器上运行多个mysql服务器? - WaiKit Kung
谢谢您的提问。我刚刚通过使用127.0.0.1而不是localhost大大加快了我的网站速度。 - 1' OR 1 --
2个回答

29

PHP 正在尝试连接到本地主机。由于您的计算机通过 IPv6 连接到网络,它首先尝试使用 IPv6 版本的“localhost”,即 IP 地址为 ::1。

http://en.wikipedia.org/wiki/IPv6_address#Special_addresses

::1/128 - 回环地址是单播本地主机地址。如果主机中的应用程序向此地址发送数据包,则IPv6堆栈将在同一虚拟接口上将这些数据包回送(对应于IPv4中的127.0.0.0/8)。
看起来您的MySQL服务器没有侦听该地址,而是仅绑定到IPv4地址,因此一旦PHP无法打开连接,它就会回退并尝试通过IPv4即127.0.0.1打开本地主机。
我个人更喜欢使用IP地址或使用Windows hosts文件或Mac等效文件来定义“虚假”域名,然后在连接到MySQL时使用这些域名,这些域名解析为IP地址。无论哪种方式,我都可以确切地知道将使用IPv4还是IPv6地址。
MySQL和Apache都支持IPv6,但必须明确告诉它们使用IPv6地址。有关MySQL,请参见: http://dev.mysql.com/doc/refman/5.5/en/ipv6-server-config.html

有关Apache配置,请参见: http://httpd.apache.org/docs/2.2/bind.html

Apache支持多个IP地址,因此如果机器上的网络卡具有IPv4和IPv6地址,则可以同时使用两者。MySQL仅支持一个地址。


我已经采取了一些步骤来查看问题。首先,我进入C:/Windows/System32/drivers/etc/查看Windows主机文件,并发现所有信息都被注释掉了。因此,我取消了“127.0.0.1 localhost”的注释并执行了MySQL连接。执行时间约为10毫秒。然后我回到主机文件,注释掉“127.0.0.1 localhost”并取消注释“::1 localhost”。之后,我再次运行程序。结果,程序无法连接到MySQL服务器。 - WaiKit Kung
MySQL服务器的版本是5.1.03。因此,我得出结论,问题可能是由于Mysql服务器不支持ipv6所致。因此,解决方案可能是避免使用ipv6或启用MySQL服务器ipv6支持。欢迎任何建议和补充。 - WaiKit Kung
我通过cmd使用"netstat -an"命令,并发现有两行输出:"TCP 0.0.0.0:80 0.0.0.0:0 LISTENING"和"TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING"。但是没有[::]:80或[::]:3306。这是否意味着Apache和MySQL都不支持IPv6? - WaiKit Kung
他们支持它们 - 在主答案中添加了链接。 - Danack

11

PHP试图在Windows 7/8/10中连接到“localhost”,但实际上是::1,而MySQL没有监听IPv6套接字,您可以应用以下几个修复方法:

1)在主机文件(C:/windows/system32/drivers/etc/host)中将localhost设置为127.0.0.1

2)在PHP中将MySQL服务器从localhost更改为127.0.0.1

3)在my.ini中添加或编辑:bind-address = ::

  

如果地址为::,则服务器将接受所有服务器主机IPv4和IPv6接口上的TCP/IP连接。使用此地址允许在所有服务器接口上进行IPv4和IPv6连接。

建议选项,如果您的MySQL版本>=5.5.3


1
bind-address = :: 帮了我! - Evan Lee
@marcovtwout 你用的是哪个版本的MySQL?出现了什么错误? - Jose Nobile
如果我理解正确的话,从hosts文件中解析到本地主机已经不再使用了。请参考https://dev59.com/5mgu5IYBdhLWcg3wdGwb#15436435。 - marcovtwout
从我的测试来看,本地主机遵循主机文件。无论如何,推荐的选项是#3。 - Jose Nobile

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