問題描述
我在這里問這個是因為我認為它不僅僅適用于 EasyPHP 本身.
I'm asking this here because I think it applies to more than just EasyPHP itself.
我目前使用 EasyPHP 作為我的 WAMP 開發服務器,因此我可以創建 Web 應用程序.問題是,當我讓 mysqli 對象連接到數據庫時,它需要 1 秒.在共享主機上運行相同的查詢會導致速度提高 200 倍以上.這是我應該擔心的事情嗎?在可擴展性或將我的應用程序移動到另一臺服務器方面,花點時間看看問題是什么是明智的嗎?我只是假設 EasyPHP 可能很慢.不是專業,只是讓我覺得有趣的事情.
I currently use EasyPHP as my WAMP development server so I can create web applications. The problem is, when I get the mysqli object to connect to the database it takes 1 second. Running the same query on shared hosting results in speeds over 200 times faster. Should this be something I should be worried about? In terms of scalability or moving my application to another server would it be smart to spend a while seeing what the issue is? I just assumed that perhaps EasyPHP was slow. Not a major, just something that struck me as interesting.
推薦答案
如果您遇到此問題并且使用的是 Windows 7 之前的 Windows 版本,這可能不是您問題的答案.
為什么會這樣?
這個問題的原因是 IPv4 vs IPv6.
The cause of this problem is IPv4 vs IPv6.
當您使用主機名而不是 IP 地址時,MySQL 客戶端首先運行 AAAA
(IPv6) 主機查找名稱,如果成功將名稱解析為IPv6 地址.如果任一步驟失敗(名稱解析或連接),它將回退到 IPv4,運行 A
查找并嘗試使用此主機.
When you use a host name instead of an IP address, the MySQL client first runs an AAAA
(IPv6) host lookup for the name, and tries this address first if it successfully resolves the name to an IPv6 address. If either step fails (name resolution or connection) it will fallback to IPv4, running an A
lookup and trying this host instead.
這在實踐中意味著如果 IPv6 localhost
查找成功但 MySQL 未綁定到 IPv6 環回,您將需要等待一個連接超時周期(顯然在 OP 的機器上)這是發生 IPv4 回退和連接成功之前的 1 秒).
What this means in practice is that if the IPv6 localhost
lookup is successful but MySQL is not bound to the IPv6 loopback, you will need to wait for one connection timeout cycle (evidently on the OP's machine this is 1 second) before the IPv4 fallback occurs and the connection succeeds.
這在 Windows 7 之前不是問題,因為 localhost
解析是通過主機文件完成的,并且它只預先配置了 127.0.0.1
- 它沒有附帶它的 IPv6 對應物 ::1
.
This was not an issue prior to Windows 7, because localhost
resolution was done via the hosts file, and it came preconfigured with only 127.0.0.1
- it did not come with it's IPv6 counterpart ::1
.
但是,從 Windows 7 開始,localhost
解析內置于 DNS 解析器中,原因在此處.這意味著 IPv6 查找現在將成功 - 但 MySQL 未綁定到該 IPv6 地址,因此連接將失敗,您將看到此問題中概述的延遲.
Since Windows 7, however, localhost
resolution is built into the DNS resolver, for reasons outlined here. This means that the IPv6 lookup will now succeed - but MySQL is not bound to that IPv6 address, so the connection will fail, and you will see the delay outlined in this question.
那很好.只要告訴我如何修復它!
您有幾個選擇.環顧互聯網,一般的解決方案"似乎是顯式使用 IP 地址而不是名稱,但有幾個原因不這樣做,兩者都與可移植性有關,兩者都可以說都不重要:
You have a few options. Looking around the internet, the general "solution" seems to be to use the IP address explicitly instead of the name, but there are a couple of reasons not to do this, both portability related, both arguably not important:
如果您將腳本移到另一臺僅支持 IPv6 的機器上,您的腳本將不再起作用.
If you move your script to another machine that only supports IPv6, your script will no longer work.
如果您將腳本移至基于 *nix 的托管環境,則魔術字符串 localhost
將意味著 MySQL 客戶端更喜歡使用 Unix 套接字(如果已配置),這是比基于 IP 環回的連接更有效
If you move your script to a *nix-based hosting environment, the magic string localhost
would mean the MySQL client would prefer to use a Unix socket if one is configured, this is more efficient than IP loopback based connectivity
它們聽起來很重要嗎?
他們不是.您應該設計您的應用程序,以便在配置文件中定義此類內容.如果您將腳本移至其他環境,則可能還需要配置其他內容.
They aren't. You should be designing your application so that this sort of thing is defined in a configuration file. If you move your script to another environment, chances are other things will need configuring as well.
總而言之,使用 IP 地址不是最佳解決方案,但很可能是可接受的解決方案.
In summary, using the IP address is not the best solution, but it is most likely an acceptable one.
那么最好的解決方案是什么?
最好的方法是更改?? MySQL 服務器使用的綁定地址.然而,這并不像人們想象的那么簡單.與 Apache、Nginx 和幾乎所有其他健全的網絡服務應用程序不同,MySQL 僅支持單個綁定地址,因此它不僅僅是添加另一個綁定地址的情況.幸運的是,操作系統確實在這里支持了一些魔法,因此我們可以讓 MySQL 同時使用 IPv4 和 IPv6.
The best way would be to change the bind address that the MySQL server uses. However, this is not as simple as one might like. Unlike Apache, Nginx and almost every other sane network service application ever made, MySQL only supports a single bind address, so it's not just a case of adding another one. Luckily though, operating systems do support a bit of magic here, so we can enable MySQL to use both IPv4 and IPv6 simultaneously.
您需要運行 MySQL 5.5.3 或更高版本,并且您需要使用 --bind-address=
命令行參數啟動 MySQL(或在 my.ini 中設置相應選項).您有 4 個選項docs,取決于你想做什么:
You need to be running MySQL 5.5.3 or later, and you need to start MySQL with the --bind-address=
command line argument (or set the corresponding option in my.ini). You have 4 optionsdocs, depending on what you want to do:
您可能熟悉,并且最有可能(有效)使用的那個,
0.0.0.0
.這將綁定到機器上所有可用的 IPv4 地址.即使您不關心 IPv6,這實際上也可能不是最好的做法,因為它面臨與::
相同的安全風險.
The one you are probably familiar with, and the one that you are most likely (effectively) using,
0.0.0.0
. This binds to all available IPv4 addresses on the machine. This actually is probably not the best thing to do even if you don't care about IPv6, as it suffers the same security risks as::
.
顯式 IPv4 或 IPv6 地址(例如 127.0.0.1
或 ::1
用于環回).這會將服務器綁定到該地址并且僅該地址.
An explicit IPv4 or IPv6 address (for example 127.0.0.1
or ::1
for loopback). This binds the server to that address and only that address.
魔法字符串::
.這將在 IPv4 和 IPv6 模式下將 MySQL 綁定到機器上的每個地址,包括環回和物理接口地址.這可能存在安全風險,僅當您需要 MySQL 接受來自遠程主機的連接時才這樣做.
The magic string ::
. This will bind MySQL to every address on the machine, both loopback and physical interface addresses, in IPv4 and IPv6 mode. This is potentially a security risk, only do this if you need MySQL to accept connections from remote hosts.
使用IPv4 映射的 IPv6 地址.這是 IPv6 中內置的一種特殊機制,用于在 4 -> 6 轉換期間向后兼容,它允許您綁定到特定的 IPv4 地址,它與 IPv6 等效.除了雙環回"地址 ::ffff:127.0.0.1
之外,這對您不太可能有用.對于大多數人來說,這很可能是最好的解決方案,僅綁定到環回但允許 IPv4 和 IPv6 連接.
Use an IPv4-mapped IPv6 address. This is a special mechanism built into IPv6 for backwards compatibility during the 4 -> 6 transition, and it allows you bind to a specific IPv4 address and it's IPv6 equivalent. This is quite unlikely to be useful to you for anything other than the "dual loopback" address ::ffff:127.0.0.1
. This is most likely the best solution for most people, only binding to the loopback but allowing both IPv4 and IPv6 connections.
我需要修改hosts文件嗎?
否.不要修改主機文件.DNS 解析器知道如何處理 localhost
,重新定義它充其量沒有任何效果,最壞的情況是混淆解析器.
NO. Don't modify the hosts file. The DNS resolver knows what to do with localhost
, redefining it will at best have no effect, and at worst confuse the hell out of the resolver.
<代碼>--skip-name-resolve?
這也可能解決問題/需要解決問題,原因相關但略有不同.
This may also fix the problem/be required to fix the problem, for a related but slightly different reason.
如果沒有此配置選項,MySQL 將嘗試通過 PTR
DNS 查詢將所有客戶端連接 IP 地址解析為主機名.如果您的 MySQL 服務器已經啟用使用 IPv6 但連接仍然需要很長時間,這可能是因為反向 DNS (PTR
) 記錄沒有正確配置.
Without this configuration option, MySQL will attempt to resolve all client connection IP addresses to a hostname via a PTR
DNS query. If your MySQL server is already enabled to use IPv6 but connections are still taking a long time, it may be because the reverse DNS (PTR
) record is not correctly configured.
禁用名稱解析將解決此問題,但它確實有其他后果,特別是在 Host
條件中配置為使用 DNS 名稱的任何訪問權限現在都將失敗.
Disabling name resolution will fix this problem, but it does have other ramifications, notably that any access permissions configured to use a DNS name in the Host
condition will now fail.
如果您打算這樣做,您需要將所有授權配置為使用 IP 地址而不是名稱.
If you are going to do this, you will need to configure all your grants to use IP addresses instead of names.
這篇關于PHP到EasyPHP MySQL服務器1秒連接延遲的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!