Dies ist fast wörtlich aus meiner Antwort hier entnommen , aber ich weiß, dass wir bei SO-Antworten nur auf Links die Stirn runzeln, also stelle ich mir vor, dass ihr es auch tut :-)
Wenn Sie dieses Problem haben und eine Windows-Version vor Windows 7 verwenden, ist dies wahrscheinlich nicht die Antwort auf Ihr Problem.
Warum passiert das?
Die Ursache für dieses Problem ist IPv4 vs IPv6.
Wenn Sie anstelle einer IP-Adresse einen Hostnamen verwenden, führt der MySQL-Client zuerst eine AAAA
IPv6-Hostsuche nach dem Namen durch und versucht diese Adresse zuerst, wenn der Name erfolgreich in eine IPv6-Adresse aufgelöst wird. Wenn einer der Schritte fehlschlägt (Namensauflösung oder Verbindung), wird auf IPv4 zurückgegriffen, eine A
Suche ausgeführt und stattdessen dieser Host getestet.
In der Praxis bedeutet dies, dass Sie, wenn die IPv6- localhost
Suche erfolgreich ist, MySQL jedoch nicht an den IPv6-Loopback gebunden ist, einen Verbindungszeitüberschreitungszyklus abwarten müssen, bevor der IPv4-Fallback auftritt und die Verbindung erfolgreich ist.
Dies war vor Windows 7 kein Problem, da die localhost
Lösung über die Hosts-Datei erfolgte und nur mit vorkonfiguriertem 127.0.0.1
IPv6-Gegenstück geliefert wurde ::1
.
Seit Windows 7 localhost
ist die Auflösung jedoch aus den hier beschriebenen Gründen in den DNS-Resolver integriert . Dies bedeutet, dass die IPv6-Suche nun erfolgreich ist. MySQL ist jedoch nicht an diese IPv6-Adresse gebunden, sodass die Verbindung fehlschlägt und die in dieser Frage angegebene Verzögerung angezeigt wird.
Das ist schön. Sagen Sie mir einfach, wie ich das Problem beheben kann!
Sie haben ein paar Möglichkeiten. Wenn Sie sich im Internet umsehen, scheint die allgemeine "Lösung" darin zu bestehen, die IP-Adresse explizit anstelle des Namens zu verwenden. Es gibt jedoch eine Reihe von Gründen, warum Sie dies nicht tun sollten. Beide Gründe hängen mit der Portabilität zusammen, beide sind vermutlich nicht wichtig:
Wenn Sie Ihr Skript auf einen anderen Computer verschieben, der nur IPv6 unterstützt, funktioniert Ihr Skript nicht mehr.
Wenn Sie Ihr Skript in eine * nix-basierte Hosting-Umgebung verschieben, würde die magische Zeichenfolge localhost
bedeuten, dass der MySQL-Client lieber einen Unix-Socket verwenden würde, wenn einer konfiguriert ist. Dies ist effizienter als eine IP-Loopback-basierte Konnektivität
Sie klingen aber ziemlich wichtig?
Sie sind nicht. Sie sollten Ihre Anwendung so gestalten, dass dies in einer Konfigurationsdatei definiert ist. Wenn Sie Ihr Skript in eine andere Umgebung verschieben, müssen möglicherweise auch andere Dinge konfiguriert werden.
Zusammenfassend ist die Verwendung der IP-Adresse nicht die beste Lösung, aber höchstwahrscheinlich eine akzeptable.
Also, was ist die beste Lösung?
Am besten ändern Sie die Bindungsadresse, die der MySQL-Server verwendet. Dies ist jedoch nicht so einfach, wie man möchte. Im Gegensatz zu Apache, Nginx und fast jeder anderen vernünftigen Netzwerkdienstanwendung, die jemals erstellt wurde, unterstützt MySQL nur eine einzige Bindungsadresse, sodass nicht nur eine weitere hinzugefügt werden muss. Glücklicherweise unterstützen Betriebssysteme hier ein bisschen Magie, sodass MySQL IPv4 und IPv6 gleichzeitig verwenden kann.
Sie müssen MySQL 5.5.3 oder höher ausführen und MySQL mit dem --bind-address=
Befehlszeilenargument starten . Sie haben 4 Optionen docs , je nachdem , was Sie tun möchten:
Die Sie wahrscheinlich vertraut sind, und die, die Sie am ehesten (effektiv) Verwendung 0.0.0.0
. Dies bindet an alle verfügbaren IPv4-Adressen auf dem Computer. Dies ist wahrscheinlich auch dann nicht das Beste, wenn Sie sich nicht für IPv6 interessieren, da es die gleichen Sicherheitsrisiken wie IPv6 aufweist ::
.
Eine explizite IPv4- oder IPv6-Adresse (zum Beispiel 127.0.0.1
oder ::1
für Loopback). Dadurch wird der Server an diese Adresse und nur an diese Adresse gebunden.
Die magische Schnur ::
. Dadurch wird MySQL im IPv4- und IPv6-Modus an alle Adressen auf dem Computer gebunden, sowohl Loopback- als auch physikalische Schnittstellenadressen. Dies ist möglicherweise ein Sicherheitsrisiko. Tun Sie dies nur, wenn Sie MySQL benötigen, um Verbindungen von Remote-Hosts zu akzeptieren.
Verwenden Sie eine IPv4-zugeordnete IPv6-Adresse . Dies ist ein spezieller Mechanismus, der in IPv6 integriert ist, um die Abwärtskompatibilität während des 4 -> 6-Übergangs zu gewährleisten. Er ermöglicht das Binden an eine bestimmte IPv4-Adresse und deren IPv6-Äquivalent. Es ist ziemlich unwahrscheinlich, dass dies für Sie für etwas anderes als die "Dual Loopback" -Adresse nützlich ist ::ffff:127.0.0.1
. Dies ist höchstwahrscheinlich die beste Lösung für die meisten Benutzer, da sie nur an das Loopback gebunden sind, aber sowohl IPv4- als auch IPv6-Verbindungen zulassen.
Muss ich die hosts-Datei ändern?
NO . Ändern Sie nicht die Hosts-Datei. Der DNS-Resolver weiß, was zu tun localhost
ist. Eine Neudefinition hat bestenfalls keine Auswirkungen und verwirrt im schlimmsten Fall den Resolver.
Was ist --skip-name-resolve
?
Dies kann das Problem auch aus einem verwandten, aber etwas anderen Grund beheben.
Ohne diese Konfigurationsoption versucht MySQL, alle IP-Adressen der Client-Verbindung über eine PTR
DNS-Abfrage in einen Hostnamen aufzulösen . Wenn Ihr MySQL-Server bereits für die Verwendung von IPv6 aktiviert ist, die Verbindungen jedoch noch lange dauern, liegt dies möglicherweise daran, dass der Reverse-DNS ( PTR
) -Datensatz nicht richtig konfiguriert ist.
Das Deaktivieren der Namensauflösung behebt dieses Problem, hat jedoch andere Konsequenzen, insbesondere, dass alle Zugriffsberechtigungen, die für die Verwendung eines DNS-Namens in der Host
Bedingung konfiguriert sind, jetzt fehlschlagen.
In diesem Fall müssen Sie alle Ihre Berechtigungen so konfigurieren, dass IP-Adressen anstelle von Namen verwendet werden.