【问题标题】:PHP to EasyPHP MySQL server 1 second connection delayPHP 到 EasyPHP MySQL 服务器 1 秒连接延迟
【发布时间】:2012-07-03 20:44:44
【问题描述】:

我在这里问这个问题是因为我认为它不仅仅适用于 EasyPHP 本身。

我目前使用 EasyPHP 作为我的 WAMP 开发服务器,因此我可以创建 Web 应用程序。问题是,当我让 mysqli 对象连接到数据库时,它需要 1 秒。在共享主机上运行相同的查询会导致速度快 200 倍以上。这应该是我应该担心的事情吗?就可扩展性或将我的应用程序移动到另一台服务器而言,花点时间看看问题所在是否明智?我只是假设 EasyPHP 可能很慢。不是专业,只是让我觉得很有趣。

【问题讨论】:

    标签: php mysqli easyphp


    【解决方案1】:

    如果您遇到此问题并使用 Windows 7 之前的 Windows 版本,这可能不是您问题的答案。

    为什么会这样?

    此问题的原因是 IPv4 与 IPv6。

    当您使用主机名而不是 IP 地址时,MySQL 客户端首先运行 AAAA (IPv6) 主机查找名称,如果成功将名称解析为 IPv6 地址,则首先尝试此地址。如果任一步骤失败(名称解析或连接),它将回退到 IPv4,运行A 查找并尝试此主机。

    这实际上意味着如果 IPv6 localhost 查找成功但 MySQL 未绑定到 IPv6 环回,您将需要等待一个连接超时周期(显然在 OP 的机器上这是 1 秒)在 IPv4 回退发生并且连接成功之前。

    这在 Windows 7 之前不是问题,因为 localhost 解析是通过 hosts 文件完成的,并且仅预配置了 127.0.0.1 - 它没有与 IPv6 对应的 ::1 一起提供。

    然而,从 Windows 7 开始,localhost 解析内置于 DNS 解析器中,原因已概述为 here。这意味着 IPv6 查找现在将成功 - 但 MySQL 未绑定到该 IPv6 地址,因此连接将失败,您将看到此问题中概述的延迟。

    很好。告诉我如何解决它!

    您有几个选择。环顾互联网,一般的“解决方案”似乎是明确使用 IP 地址而不是名称,但有几个原因不这样做,两者都与可移植性有关,都可以说都不重要:

    • 如果您将脚本移动到另一台支持 IPv6 的计算机上,您的脚本将不再工作。

    • 如果你将你的脚本移动到一个基于 *nix 的宿主环境中,localhost 的魔法字符串意味着如果配置了一个 Unix 套接字,MySQL 客户端会更喜欢使用,这比 IP 环回更有效基于连接

    但它们听起来很重要?

    他们不是。您应该设计您的应用程序,以便在配置文件中定义此类事情。如果您将脚本移动到另一个环境,可能还需要配置其他内容。

    总而言之,使用 IP 地址不是最佳解决方案,但它很可能是可接受的解决方案。

    那么最好的解决方案是什么?

    最好的方法是更改​​ MySQL 服务器使用的绑定地址。然而,这并不像人们想象的那么简单。与 Apache、Nginx 和几乎所有其他健全的网络服务应用程序不同,MySQL 仅支持单个绑定地址,因此不仅仅是添加另一个绑定地址的情况。不过幸运的是,操作系统在这里确实支持了一些魔法,所以我们可以让 MySQL 同时使用 IPv4 和 IPv6。

    您需要运行 MySQL 5.5.3 或更高版本,并且需要使用--bind-address= 命令行参数(或在 my.ini 中设置相应选项)启动 MySQL。您有 4 个选项docs,具体取决于您想做什么:

    • 您可能熟悉且最有可能(有效)使用的一种,0.0.0.0。这将绑定到机器上所有可用的 IPv4 地址。即使您不关心 IPv6,这实际上也可能不是最好的做法,因为它面临与 :: 相同的安全风险。

    • 显式 IPv4 或 IPv6 地址(例如 127.0.0.1::1 用于环回)。这会将服务器绑定到该地址并且该地址。

    • 魔线::。这将在 IPv4 和 IPv6 模式下将 MySQL 绑定到机器上的每个地址,包括环回和物理接口地址。这存在潜在的安全风险,仅当您需要 MySQL 接受来自远程主机的连接时才这样做。

    • 使用IPv4-mapped IPv6 address。这是 IPv6 中内置的一种特殊机制,用于在 4 -> 6 转换期间向后兼容,它允许您绑定到特定的 IPv4 地址,它是 IPv6 的等效地址。除了“双环回”地址::ffff:127.0.0.1 之外,这不太可能对您有用。对于大多数人来说,这很可能是最好的解决方案,只绑定到环回但同时允许 IPv4 和 IPv6 连接。

    需要修改 hosts 文件吗?

    。不要修改主机文件。 DNS 解析器知道如何处理localhost,重新定义它充其量不会产生任何效果,最坏的情况是会混淆解析器。

    --skip-name-resolve 呢?

    出于相关但略有不同的原因,这也可能解决问题/需要解决问题。

    如果没有此配置选项,MySQL 将尝试通过PTR DNS 查询将所有客户端连接 IP 地址解析为主机名。如果您的 MySQL 服务器已经启用了使用 IPv6,但连接仍然需要很长时间,可能是因为反向 DNS (PTR) 记录配置不正确。

    禁用名称解析将解决此问题,但它确实有其他后果,特别是配置为在 Host 条件中使用 DNS 名称的任何访问权限现在都将失败。

    如果您要这样做,您需要将所有授权配置为使用 IP 地址而不是名称。

    【讨论】:

    • TL;博士!大声笑,实际上,这个答案是完美的。你知道 MySQL 5.6 是否解决了这个问题吗?我可能会升级。 (但是,说真的,没有 jQuery?)
    • 对于 mysql 查询非常慢的 Windows 8 机器来说,这似乎是一个非常常见的问题(对 SEO 的评论)。
    • 我迟到了 2 年,但我刚刚将接受的答案更改为您的答案。谢谢。
    • TLDR:在开发机器上,打开 my.ini 并设置:bind-address=::(可选择让您的防火墙阻止远程访问)
    • 这救了我的命!如果您在 docker 容器中运行 mysql,请确保您的 [mysqld] 配置文件中有 skip-host-cacheskip-name-resolve 行。响应时间缩短 4~5s 至 0.02ms
    【解决方案2】:

    当我使用localhost 作为 MySQL 服务器地址时,我遇到了一些延迟。将其更改为 127.0.0.1 有帮助。

    【讨论】:

    • 好吧,你太棒了。太感谢了。我将主机更改为 127.0.0.1,我的页面在 0.0074560547 秒内执行。感激不尽。
    【解决方案3】:

    无论服务器如何,只要有可能,最好使用持久连接。毕竟,在旧连接也可以完成工作时,一直打开新连接是不明智的。查看 mysqli 的 manual

    【讨论】:

    • 我遇到了持久连接的问题 - PHP 有时会尝试创建新连接,尽管存在“免费”现有连接,这会导致“连接过多”错误。不过那是几年前的事了,所以它可能已经修复(或者甚至可能是本地问题)。
    • 一定是修好了。 mysqli 的持久连接是在 PHP 5.3 中引入的,所以它们并没有那么旧。
    • 我相信我在使用 PDO 或旧的 mysql 函数时遇到了问题。从未真正使用过mysqli。
    • 我在脚本开始时打开连接并在结束时关闭它。那不是持久连接吗?
    • 阅读手册,不太喜欢持久连接的外观。
    猜你喜欢
    • 2012-12-01
    • 2018-08-09
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    • 2021-03-07
    相关资源
    最近更新 更多