XAMPP で MySQL 接続がやたらと遅い件

この記事は最終更新日から 12年以上 が経過しています。

XAMPP 環境にて作業を行っていたところ、MySQL 接続がやたらと遅く辟易したため、原因を調査してみた。 少々ハマってしまったので、ここに書いておきます。誰かの役に立てば幸いだ。

ことの発端

現象

現象としては、PHP から MySQL への接続に1秒以上かかるというもの。 ソースコードは下記のたった1行のみ。

PHP
mysqli_connect('localhost', 'user', 'password', 'dbname');

ごらんの通り、ただ MySQL に接続するだけのコードである。 たったこれだけで1秒以上かかってしまう。どう考えても遅すぎる。 ちなみに正常な場合は、遅くても 0.01 秒ほど。 空いた口が塞がらなくて顎が外れそうだ。

環境

調査して判明したことだが、この問題はかなり特殊な環境依存問題なので、ここにバージョンを記しておく。 結論からいえば、この問題は Windows Vista/7 + PHP + MySQL という組み合わせ、 つまりは Windows Vista/7 上の XAMPP 環境で発生する。

OS Windows 7 64bit
XAMPP 1.8.0
PHP 5.4.4
MySQL 5.5.25a

原因

判明した原因は下記の通り。

Windows Vista/7 では、 localhost の名前解決に DNS が使われるようになった

hosts ファイルにはこう書いてあり、localhost の記述はコメントアウトされている。

hosts ファイル
# localhost name resolution is handled within DNS itself.
#	127.0.0.1		localhost
#	::1 			localhost

Windows Vista/7 では、localhost の名前解決は DNS によって行われるようになっているよう(デフォルトの hosts ファイルでは)。 これはどうも Windows Vista/7 時代からのようで、XP 時代では無かったことのようです。 IPv4 か IPv6 のどちらかのコメントアウトを外すことで、外した方を使用することが可能になりますが、 両方ともコメントアウトされていると、IPv6 の方が優先され、ダメなら IPv4 でというような動作となっているようです。

理由は、現在は IPv4 と IPv6 の過渡期なので同時稼働ということになってはいますが、 将来的には IPv4 は無効化されるということが強く想定されているためとのこと。 IPv4 が無効な状態のときに、IPv4 のアドレスに解決されてしまうと困るので、 DNS で解決するようにして切り替えられるようにということらしい。

IPv4 アドレス IPv6 アドレス 動作
両方ともコメントアウト(もしくは両方とも有効?) DNS によって IPv6 と IPv4 を動的に解決
有効 無効(コメントアウト) hosts ファイルに従って IPv4 アドレスを使用
無効(コメントアウト) 有効 hosts ファイルに従って IPv6 アドレスを使用

ここで注目なのは、両方ともコメントアウト状態だと、DNS が使われるということです。

DBサーバーへの接続にも名前解決が必要

IP 上で動作している以上は当たり前なのかもですが、 Web サーバーから DB サーバーへの接続の際に、接続先の DB サーバーをホスト名で指定した場合、 そのホスト名を名前解決する必要があります。

そして今回の原因はまさにその接続先のホスト名に "localhost" と指定することによって、 DNS によって名前解決される必要性が発生し、その結果、処理の遅延が発生したと考えられます。

試しに、接続先のホスト名に "127.0.0.1" と指定した場合には、名前解決をする必要が無いため処理の遅延は発生しません。 また、接続先のホスト名を "localhost" と指定したままの状態で、hosts ファイルの IPv4 のコメントアウトを外した場合も、 DNS が使用されないため、処理の遅延は発生しません。

まとめ

再現方法

  • 1. OS が Windows Vista/7 である。
  • 2. hosts ファイルの "localhost" の指定が IPv4、IPv6 共にコメントアウトされている。
  • 3. PHP から MySQL への接続先のホスト名に "127.0.0.1" ではなく "localhost" と指定している。

上記の条件が全て満たされた場合に、この現象は再現します。

解決方法

ということは、上記のいずれかの条件を満たさないようにすれば良いわけです。 1 は OS を変えなければならないのでそう簡単ではなく、 2 は IPv4 のコメントアウトを外せば解決しますが、IPv6 を外すと今度は繋がらなくなります。 問題の局所性を考えればあまりお勧めしません(この変更はシステム全体に影響するので)。 ということで 3 をなんとかするのが一番簡単な解決方法かと。

つまり...

PHP
// これを
mysqli_connect('localhost', 'user', 'password', 'dbname');

// こう変更すれば良い...
mysqli_connect('127.0.0.1', 'user', 'password', 'dbname');

ナ ナンダッテー!!
Ω ΩΩ

補足

my.cnf で skip-name-resolve を有効にするという方法もあるようです。

参考サイト

関連記事

XAMPP で開発する際に、PHP のメール送信関数 mail() もしくは mb_send_mail() を使うと、エラーが出てしまい困ることがあります。ちゃんとメールサーバーの設定をすれば良いじゃないかと思うかもですが、メールサーバーを用意するのは面倒ですし、実際にメールが外部に送信されてしまってもそれはそれで困り ...
最近のWebアプリでは、キャッシュやセッションを保存する際に、Redis がよく使われていたりします。しかしながら Redis は XAMPP には含まれていないため、XAMPP から Redis を使うためには XAMPP の環境に少し手を加える必要があります。そこで、その手順を記載しておきます。いまさら感も多々あり ...
この記事は古い内容です。同じ内容の改訂版の記事があります。「XAMPP に ImageMagick をインストールする方法【2023年改訂版】」XAMPP に ImageMagick をインストールする方法がかなりわかりづらく混乱してしまったので、ここにインストール方法を記載しておきます。自分への備忘録です。Image ...

記事検索

最新記事

人気記事

RSSフィード

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(旧 Twitter) もしくは、お問い合わせより、お願いします。