Ich habe gerade eine Neuinstallation von XAMPP durchgeführt. Beim ersten Öffnen von PHPMyAdmin ist mir aufgefallen, dass es extrem langsam ist. Es machte keinen Sinn, dass es auf localhost fast 5 Sekunden dauern sollte, bis sich jede Seite öffnet. Ich habe einen kleinen Testfall gemacht, um die Schuld von PHPMyAdmin abzuwenden:
$con = new PDO("mysql:host=localhost;dbname=mysql", "root", "");
$statement = $con->query('SELECT host,user,password FROM user;');
$users = $statement->fetchAll(PDO::FETCH_ASSOC);
Die Ausführung des obigen Skripts dauert nur ca. 3 Sekunden (obwohl das Laden beim ersten Ausführen knapp 8 Sekunden dauerte.)
Um dann zu überprüfen, ob es der Fehler von PDO war, habe ich mysql_connect
stattdessen versucht, Folgendes zu verwenden:
$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');
Es dauert genau so lange, bis es fertig ist.
Anfangs dachte ich, es sei PHPs Fehler, aber PHP-Code und statische Dateien werden schneller geliefert, als ich auf Aktualisieren klicken kann. Ich habe PHP getestet, indem ich dieses kleine Skript ausgeführt habe:
header("Content-Type: text/plain");
for($i = 0; $i < 5000; $i++)
{
echo sha1(rand()) . "\n";
}
5000 sha1
Berechnungen und die Seite wird immer noch schneller angezeigt, als ich mein Fenster aktualisieren kann.
Dann dachte ich, es sei MySQLs Schuld. Aber ich habe auch nicht viel getestet, um herauszufinden, dass MySQL schneller funktioniert, als ich es brauche. Mit dem MySQL CLI-Client nimmt die Benutzerauswahlabfrage nicht einmal messbare Zeit in Anspruch - sie wird durchgeführt, bevor ich die Return-Taste überhaupt losgelassen habe.
Das Problem muss die PHP-Verbindung zu MySQL sein - soweit ich es begründen konnte. Ich kann Unmengen von Dingen finden, bei denen PHP langsam oder MySQL langsam ist, aber nichts, bei denen PHP + MySQL extrem langsam ist.
Vielen Dank an alle, die mir bei der Lösung helfen können!
Ich benutze XAMPP 1.8.0 für Win32 ( Download-Link )
PHP-Version: 5.4.4
MySQL-Version: 14.14
BEARBEITEN: Nach dem Timing stellt sich heraus, dass es die Verbindungsfunktion ist, die so lange dauert:
$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);
Ausgabe:
Verbindungszeit: 1.006148 Abfragezeit: 0.000247
Was kann dazu führen, dass PHP viel Zeit mit dem Herstellen einer Verbindung zur Datenbank verbringt? Der CLI-Client, HeidiSQL und MySQL Workbench stellen sofort eine Verbindung her
Antworten:
Kann es sein, dass Ihre MySQL versucht, Rev-DNS-Abfrage auszuführen, wenn Sie eine Verbindung herstellen? Versuchen Sie, my.cnf, Abschnitt mysqld: Skip-Name- Resolution, hinzuzufügen .
quelle
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, eineA
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 vorkonfiguriertem127.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ätSie 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.
quelle
::1
. Leider::ffff:127.0.0.1
gab es mir weiterhin eine Verzögerung von 1 Sekunde (unabhängig von der Verwendungskip-name-resolve
oder nicht), irgendwelche Ideen warum? (unter Windows 8.1)Normalerweise sind die Verbindungen zu MySQL, wenn IPv6 auf dem Server aktiviert
localhost
ist, extrem langsam.Ändern Sie die MySQL-Serveradresse im Skript, um
127.0.0.1
das Problem zu beheben.quelle
localhost
auf den DNS-Resolver verschoben, aus dem Grund, dass @DaveRandom mit folgendem Link verbunden ist: serverfault.com/questions/4689/…localhost
. Ich hatte das gleiche Verzögerungsproblem für eine Serveradresse auf dem Formularxx.xxxx.xxxxx.xxxxx.com
. Nachdem ich den Servernamen in seine IP-Adresse geändert hatte, war das Problem behoben.Nun, es ist ziemlich offensichtlich, woran das liegt. PHP ist in einigen Dingen wirklich gut, kann aber 'localhost' nicht direkt in '127.0.0.1' übersetzen. Sie müssen dies versuchen, da dies die Ladezeit Ihrer gesamten Website-Seite erheblich verkürzt, da PHP daran gehindert wird, Ihre HOSTS-Datei zu überprüfen und die tatsächliche IP-Adresse hinter "localhost" zu ermitteln.
quelle
Das Hinzufügen dieser Zeile zu Ihrer Hosts-Datei löste das Problem für mich
Eine ausführliche Antwort finden Sie in diesem Thread: /programming/13584360/php-with-mysql-is-slow
quelle
Sie können die Verlangsamung der Abfrage auch beseitigen, indem Sie eine kleine Änderung an Ihrer Datenbankverbindungsvariablen vornehmen (die sich aus Gründen der Portabilität hoffentlich in einer von Ihren Skripten getrennten Datei befindet). Ändern Sie den Host-Wert in "127.0.0.1" anstelle von "localhost". Dadurch wird die lange DNS-Suche nach localhost umgangen.
Hoffe das hilft!
quelle