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 或在建立连接时切换到 ipaddress 127.0.0.1 来解决问题。

我想知道 PHP 上 IPv6 的问题是什么,只是想更深入地了解。谢谢。

4

2 回答 2

29

PHP 正在尝试打开到 localhost 的连接。因为您的计算机通过 IPv6 连接到您的网络,所以它首先尝试 IPv6 版本的 'localhost',它的 IP 地址为 ::1

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

::1/128 — 环回地址是单播 localhost 地址。如果主机中的应用程序将数据包发送到此地址,IPv6 堆栈会将这些数据包循环回同一虚拟接口(对应于 IPv4 中的 127.0.0.0/8)。

看起来您的 MySQL 服务器没有监听该地址,而是仅绑定到 IPv4 地址,因此一旦 PHP 无法打开连接,它就会回退并尝试通过 IPv4 aka 127.0.0.1 打开 localhost

我个人更喜欢使用 IP 地址或使用 Windows 主机文件或 Mac 等价物来定义“假”域名,然后在连接到解析为 IP 地址的 MySQL 时使用这些域名。无论哪种方式,我都可以确切地知道是使用 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 只支持一个地址。

于 2012-07-26T10:21:51.973 回答
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,建议的选项

于 2012-12-28T20:12:43.817 回答