Windows 8 で PHP から MySQL への接続が遅い場合の対処方法

ローカルの WAMP 環境で使用している MySQL データベースのレスポンスが遅い。これまでコンマ数ミリ秒で動作していたものが、PC 環境を変更したら 1 秒以上も掛かるようになってしまいました。すごく遅い。何かがつっかえているような感じ。Windows XP マシンから 8 (64bit) マシンに乗り換えてからの挙動です。

コードを削って問題の出ている箇所を探っていくと、PHP から接続する時に使用している mysqli_connect 関数にたどり着きました。

mysqli_connect(host, user, passwd, dbname)

この箇所。ここで時間が取られてしまっている。さらに調べてみると、このパラメータの host 部分で問題が生じていることが分かりました。Windows Vista からの仕様変更と相俟って、ホスト名を localhost とすることで処理が遅くなってしまうようです。

環境

localhost の名前解決

Windows Vista からは IPv4 よりも IPv6 が優先されるようにデフォルトでは設定されています。その設定で localhost に ping を飛ばすと IPv6 で応答が返ってきます。

C:>ping localhost

Windows8PC [::1]に ping を送信しています
::1 からの応答: 時間 <1ms
::1 からの応答: 時間 <1ms
::1 からの応答: 時間 <1ms
::1 からの応答: 時間 <1ms

::1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 0ms、平均 = 0ms

hosts ファイルを確認すると、一番下の箇所には次のように書かれていました。

#       127.0.0.1       localhost
#       ::1             localhost

IPv4・IPv6 双方ともにコメントアウト。これは規定値です。この場合は優先順位に従うので、環境が IPv4 であったとしてもまずは IPv6、次いで IPv4 を使用するという振る舞いになります。

IPv4 のコメントアウトを外してみたけれど……

ということは、IPv4 の方のコメントアウトを外せばそのまま IPv4 のアドレスを使用してくれて遅延もなくなるだろう……と、そんなふうに考えていたのですが駄目でした。遅いままでした。

解消方法

netsh コマンドで IPv4 を優先させたり、IPv6 をオフにしたりすることでも期待通りの動作になるようですが、とりあえずファイルを書き換えることで問題を解消することにしました。

mysqli_connect 関数の host を 127.0.0.1

ソースコードを編集する方法。host の値をホスト名ではなく IP で指定する。つまり 127.0.0.1 にします。

mysqli_connect('127.0.0.1', user, passwd, dbname)

遅延なしで一瞬で接続してくれます。あくまでここでのコネクションに使うだけですから、ブラウザなどからは http://localhost/~ でもアクセス可能です。なお、host を NULL にした場合には localhost とした場合と同じ扱いになります。

ループバックアドレスに localhost 以外のホスト名

hosts ファイルを編集する方法。任意のホスト名で 127.0.0.1 にアクセスできるように追記します。

127.0.0.1       hoge

ソースコードもそれに合わせて書き換えます。

mysqli_connect('hoge', user, passwd, dbname)

これで遅延せず繋がります。当然こちらも http://localhost/~ でもアクセス可能。とにかく関数で使うホスト名が localhost となっていることが問題の模様。

この任意名のホストは IPv4 のみの設定ですから、ping の応答ももちろんその様になっています。

C:>ping hoge

hoge [127.0.0.1]に ping を送信しています 32 バイトのデータ:
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128

127.0.0.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 0ms、平均 = 0ms

IPv6 の方も併記するとどうなるでしょう。そちらが優先されることになり、やはり接続に時間が掛かってしまうことが確認できました。

phpMyAdmin の設定

MySQL の管理ツールである phpMyAdmin もデフォルトでは localhost になっています。上記の方法で対処する場合は、config.inc.php の「Server parameters」にある該当箇所を編集します。

今日学んだこと

PHP で MySQL データベースへの接続が遅い時の対処方法。mysqli_connect 関数は IP で指定する、または localhost 以外のホスト名を使う。