我刚刚安装了XAMPP。 当第一次打开PHPMyAdmin时,我注意到它非常缓慢。 在本地主机上打开每个页面需要将近5秒钟,这是没有意义的。 我做了一个小小的testing案例,将责备推移到PHPMyAdmin上:
$con = new PDO("mysql:host=localhost;dbname=mysql", "root", ""); $statement = $con->query('SELECT host,user,password FROM user;'); $users = $statement->fetchAll(PDO::FETCH_ASSOC);
上面的脚本需要大约3秒的时间才能运行(尽pipe第一次运行时花费了将近8秒的时间)。
然后检查是否是PDO的错误我试着用mysql_connect
来代替:
$con = mysql_connect("localhost", "root", ""); mysql_select_db("mysql", $con); $result = mysql_query('SELECT host,user,password FROM user;');
完成的时间完全相同。
我以为这是PHP的错误,但PHP代码和静态文件服务比我可以点击刷新更快。 我通过运行这个小脚本来testingPHP:
header("Content-Type: text/plain"); for($i = 0; $i < 5000; $i++) { echo sha1(rand()) . "\n"; }
5000 sha1
计算和页面仍然显示比我刷新我的窗口更快捷。
然后我觉得这是MySQL的错。 但是,再次,没有太多的testing,发现MySQL的工作比我需要的更快。 使用MySQL CLI客户端,用户select查询甚至不需要花费可测量的时间,甚至在我还没有让返回键之前完成。
这个问题必须是PHP与MySQL的连接 – 就我所能理解的那样。 我可以find很多关于PHP缓慢或者MySQL慢的东西,但是关于PHP + MySQL的一切都不是很慢。
感谢任何人可以帮助我解决这个问题!
我正在使用XAMPP 1.8.0 for win32( 下载链接 )
PHP版本:5.4.4
MySQL版本:14.14
编辑:计时后,事实certificate这是连接function,这是花了这么久:
$time = microtime(true); $con = mysql_connect("localhost", "root", ""); mysql_select_db("mysql", $con); $con_time = microtime(true); $result = mysql_query('SELECT host,user,password FROM user;'); $sel_time = microtime(true); printf("Connect time: %f\nQuery time: %f\n", $con_time-$time, $sel_time-$con_time);
输出:
连接时间:1.006148 查询时间:0.000247
什么会导致PHP花费很多时间连接到数据库? CLI客户端,HeidiSQL和MySQL工作台立即连接
你可以在你连接的时候尝试运行rev-dns查询吗? 尝试添加到my.cnf,部分mysqld: skip-name-resolve 。
这几乎是从我的答案这里 ,但我知道我们皱眉只有链接的答案,所以我想你们做的一样好:-)
如果您在Windows 7之前遇到此问题并使用Windows版本,则可能无法解决您的问题。
为什么发生这种情况?
这个问题的原因是IPv4 vs IPv6。
当您使用主机名而不是IP地址时,MySQL客户端首先运行AAAA
(IPv6)主机查找名称,如果成功将名称parsing为IPv6地址,则首先尝试使用此地址。 如果任一步骤失败(名称parsing或连接),则将回退到IPv4,运行A
查找并尝试使用此主机。
这实际上意味着,如果IPv6 localhost
查找成功,但是MySQL没有绑定到IPv6回环,则需要等待一个连接超时周期,然后IPv4回退并且连接成功。
这在Windows 7之前不是问题,因为localhost
parsing是通过主机文件完成的,它只是预configuration了127.0.0.1
– 它没有与它的IPv6对应项::1
。
但是,从Windows 7开始, localhost
parsing程序就内置在DNSparsing程序中,原因如下。 这意味着IPv6查找现在将成功 – 但是MySQL不绑定到该IPv6地址,因此连接将失败,您将看到此问题中列出的延迟。
这很好。 只要告诉我如何解决它已经!
你有几个select。 环顾互联网,一般的“解决scheme”似乎是明确地使用IP地址而不是名称,但有几个原因不这样做,无论是可移植性相关,都可以说是不重要的:
如果将脚本移动到仅支持IPv6的另一台计算机,则脚本将不再工作。
如果你的脚本移动到一个基于nix的托pipe环境中,魔术stringlocalhost
将意味着MySQL客户端更喜欢使用一个Unix套接字(如果configuration的话),这比基于IP回送的连接更有效率
他们听起来很重要?
他们不是。 您应该devise您的应用程序,以便这样的事情在configuration文件中定义。 如果你把你的脚本移动到另一个环境,其他的东西也可能需要configuration。
总之,使用IP地址并不是最好的解决scheme,但它很可能是一个可以接受的解决scheme。
那么最好的解决scheme是什么?
最好的方法是更改MySQL服务器使用的绑定地址。 但是,这并不像人们想象的那么简单。 与Apache,Nginx以及其他几乎所有的networking服务应用程序不同,MySQL只支持一个绑定地址,所以不仅仅是添加另外一个地址的情况。 幸运的是,操作系统在这里确实支持一些魔法,所以我们可以使MySQL同时使用IPv4和IPv6。
您需要运行MySQL 5.5.3或更高版本,并且需要使用--bind-address=
命令行参数启动MySQL。 你有4个选项文件 ,取决于你想要做什么:
你可能熟悉的那个,你最有可能(有效)使用的那个, 0.0.0.0
。 这绑定到机器上所有可用的IPv4地址。 即使你不关心IPv6,这实际上可能不是最好的,因为它遭受与::
相同的安全风险。
一个明确的IPv4或IPv6地址(例如127.0.0.1
或::1
for loopback)。 这将服务器绑定到该地址, 只有该地址。
魔术string::
。 这将绑定MySQL到机器上的每个地址,包括环回和物理接口地址,在IPv4和IPv6模式。 这可能是一个安全风险,只有当您需要MySQL接受来自远程主机的连接时才会这样做。
使用IPv4映射的IPv6地址 。 这是一个内置于IPv6中的特殊机制,用于在4→6转换期间向后兼容,并允许您绑定到特定的IPv4地址,并且它与IPv6等效。 对于除“双重回送”地址::ffff:127.0.0.1
之外的任何内容,这都不太可能有用。 这对于大多数人来说很可能是最好的解决scheme,只能绑定到回送,但同时允许IPv4和IPv6连接。
我需要修改hosts文件吗?
NO 。 不要修改主机文件。 DNSparsing器知道如何处理localhost
,重新定义它最多不会有任何效果,最坏的情况是把解决方法搞糊涂了。
那么--skip-name-resolve
呢?
这也可以解决这个问题,一个相关的,但稍有不同的原因。
如果没有这个configuration选项,MySQL将尝试通过PTR
DNS查询将所有客户端连接IP地址parsing为主机名。 如果您的MySQL服务器已经启用了使用IPv6,但连接仍然需要很长时间,可能是因为反向DNS( PTR
)logging没有正确configuration。
禁用名称parsing可以解决这个问题,但是确实有其他的后果,特别是configuration为在Host
条件下使用DNS名称的任何访问权限现在都会失败。
如果您要这样做,您需要将所有授权configuration为使用IP地址而不是名称。
通常,当在服务器上启用IPv6时,使用localhost
连接到MySQL是非常慢的。
更改脚本中的mysql服务器地址为127.0.0.1
解决了这个问题。
mysql_connect("localhost", "root", "");
那么,原因是很明显的。 PHP真的很擅长一些东西,但不是直接把'localhost'翻译成'127.0.0.1'。 你必须这样做,它会真正降低你的整个网站的页面加载时间,因为它将PHP从检查你的HOSTS文件中拿回来,而不是在'localhost'之后得到真正的IP地址,
将此行添加到主机文件解决了我的问题
127.0.0.1 localhost
详细的答案可以在这个线程中find: https : //stackoverflow.com/questions/13584360/php-with-mysql-is-slow
你也可以通过对你的数据库连接variables进行一些小的调整来消除查询速度的减慢(为了便于携带,希望在你的脚本中有一个单独的文件)。 将主机值更改为“127.0.0.1”而不是“localhost”。 这绕过了localhost冗长的DNS查找。
希望这可以帮助!