Właśnie zrobiłem nową instalację XAMPP. Przy pierwszym otwarciu PHPMyAdmin zauważyłem, że było to bardzo wolne. Nie miało sensu, aby na localhost otwarcie każdej strony trwało prawie 5 sekund. Zrobiłem mały test, aby zrzucić winę na 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);
Uruchomienie powyższego skryptu zajmuje około 3 sekund (chociaż ładowanie przy pierwszym uruchomieniu zajęło mi około 8 sekund).
Następnie, aby sprawdzić, czy to wina ChNP, próbowałem użyć mysql_connect
zamiast tego:
$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');
Wykończenie zajmuje dokładnie tyle samo.
Początkowo myślałem, że to wina PHP, ale kod PHP i pliki statyczne są podawane szybciej, niż mogę odświeżyć. Testowałem PHP, uruchamiając ten mały skrypt:
header("Content-Type: text/plain");
for($i = 0; $i < 5000; $i++)
{
echo sha1(rand()) . "\n";
}
5000 sha1
obliczeń, a strona jest nadal wyświetlana szybciej, niż mogę odświeżyć moje okno.
Potem pomyślałem, że to wina MySQL. Ale znowu, nie wymagałem wiele testów, aby dowiedzieć się, że MySQL działa szybciej niż potrzebuję. Za pomocą klienta CLI MySQL zapytanie wyboru użytkownika nie zajmuje nawet mierzalnego czasu - jest to wykonywane, zanim jeszcze wrócę klawisz powrotu.
Problemem musi być połączenie PHP z MySQL - o ile mogłem to zrozumieć. Mogę znaleźć mnóstwo rzeczy o spowolnieniu PHP lub powolnym MySQL, ale nic o spowolnieniu PHP + MySQL.
Dziękujemy wszystkim, którzy mogą mi pomóc w rozwiązaniu tego problemu!
Używam XAMPP 1.8.0 dla win32 ( Link do pobrania )
Wersja PHP: 5.4.4
Wersja MySQL: 14.14
EDYCJA: Po upływie czasu okazuje się, że tak długo trwa funkcja łączenia:
$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);
Wynik:
Czas połączenia: 1.006148 Czas zapytania: 0,000247
Co może spowodować, że PHP spędza dużo czasu na łączeniu się z bazą danych? Klient CLI, HeidiSQL i MySQL łączą się natychmiast
Odpowiedzi:
Czy to możliwe, że mysql próbuje uruchomić zapytanie rev-dns przy każdym połączeniu? spróbuj dodać do my.cnf, sekcja mysqld: skip-name-resolver .
źródło
Zostało to zaczerpnięte niemal dosłownie z mojej odpowiedzi tutaj , ale wiem, że marszczymy brwi w odpowiedziach tylko na link w SO, więc wyobrażam sobie, że wy też tak robicie :-)
Jeśli masz ten problem i używasz wersji systemu Windows wcześniejszej niż Windows 7, prawdopodobnie nie jest to odpowiedź na Twój problem.
Dlaczego to się dzieje?
Przyczyną tego problemu jest IPv4 vs IPv6.
Gdy używasz nazwy hosta zamiast adresu IP, klient MySQL najpierw uruchamia
AAAA
wyszukiwanie hosta (IPv6) dla tej nazwy i najpierw próbuje tego adresu, jeśli pomyślnie rozpoznaje nazwę na adres IPv6. Jeśli jeden z kroków nie powiedzie się (rozpoznawanie nazw lub połączenie), nastąpi powrót do IPv4, uruchamiającA
wyszukiwanie i próbując zamiast tego tego hosta.W praktyce oznacza to, że jeśli
localhost
wyszukiwanie IPv6 zakończy się powodzeniem, ale MySQL nie jest związany z pętlą zwrotną IPv6, musisz poczekać na jeden limit czasu połączenia, zanim nastąpi awaria IPv4 i połączenie się powiedzie.Nie było to problemem przed Windows 7, ponieważ
localhost
rozwiązywanie odbywało się za pomocą pliku hosts i zostało wstępnie skonfigurowane tylko z127.0.0.1
- nie pochodziło z jego odpowiednikiem IPv6::1
.Ponieważ jednak system Windows 7
localhost
ma wbudowaną funkcję rozpoznawania nazw DNS, z powodów opisanych tutaj . Oznacza to, że wyszukiwanie IPv6 zakończy się teraz sukcesem - ale MySQL nie jest powiązany z tym adresem IPv6, więc połączenie nie powiedzie się i zobaczysz opóźnienie opisane w tym pytaniu.To miłe. Po prostu powiedz mi, jak to naprawić!
Masz kilka opcji. Rozglądając się po Internecie, wydaje się, że ogólnym „rozwiązaniem” jest jawne używanie adresu IP zamiast nazwy, ale istnieje kilka powodów, aby tego nie robić, oba związane z przenośnością, oba prawdopodobnie nieważne:
Jeśli przeniesiesz skrypt na inną maszynę, która obsługuje tylko IPv6, skrypt nie będzie już działał.
Jeśli przeniesiesz skrypt do środowiska hostingowego opartego na * nix, magiczny ciąg
localhost
oznaczałby, że klient MySQL wolałby używać gniazda Unix, jeśli jest skonfigurowane, jest to bardziej wydajne niż połączenie oparte na sprzężeniu zwrotnym IPBrzmią dość ważne?
Nie są. Powinieneś projektować swoją aplikację, aby tego rodzaju rzeczy były zdefiniowane w pliku konfiguracyjnym. Jeśli przeniesiesz skrypt do innego środowiska, są szanse, że inne rzeczy również będą wymagały konfiguracji.
Podsumowując, użycie adresu IP nie jest najlepszym rozwiązaniem, ale najprawdopodobniej jest akceptowalne.
Więc jakie jest najlepsze rozwiązanie?
Najlepszym sposobem jest zmiana adresu powiązania używanego przez serwer MySQL. Nie jest to jednak tak proste, jak mogłoby się to podobać. W przeciwieństwie do Apache, Nginx i prawie każdej innej rozsądnej aplikacji usługi sieciowej, jaką kiedykolwiek stworzono, MySQL obsługuje tylko jeden adres wiązania, więc nie chodzi tylko o dodanie kolejnego. Na szczęście systemy operacyjne obsługują tutaj trochę magii, dzięki czemu możemy umożliwić MySQL jednoczesne używanie zarówno IPv4, jak i IPv6.
Musisz uruchomić MySQL 5.5.3 lub nowszy i uruchomić MySQL z
--bind-address=
argumentem wiersza poleceń. Masz 4 opcje dokumentów , w zależności od tego, co chcesz zrobić:Ten, jesteś prawdopodobnie zna, a jeden, że jesteś najprawdopodobniej (efektywnie) za pomocą,
0.0.0.0
. Powiąże to wszystkie dostępne adresy IPv4 na komputerze. To prawdopodobnie nie jest najlepsza rzecz, nawet jeśli nie zależy ci na IPv6, ponieważ wiąże się to z takimi samymi zagrożeniami bezpieczeństwa jak::
.Jawny adres IPv4 lub IPv6 (na przykład
127.0.0.1
lub::1
do sprzężenia zwrotnego). To wiąże serwer z tym adresem i tylko z tym adresem.Magiczny sznurek
::
. Spowoduje to powiązanie MySQL z każdym adresem na maszynie, zarówno sprzężeniem zwrotnym, jak i fizycznym adresem interfejsu, w trybie IPv4 i IPv6. Jest to potencjalnie zagrożenie bezpieczeństwa, rób to tylko wtedy, gdy potrzebujesz MySQL do akceptowania połączeń ze zdalnych hostów.Użyj adresu IPv6 odwzorowanego na IPv4 . Jest to specjalny mechanizm wbudowany w IPv6 w celu zapewnienia wstecznej kompatybilności podczas przejścia 4 -> 6 i pozwala na powiązanie z określonym adresem IPv4 i jego odpowiednikiem IPv6. Jest to mało prawdopodobne, aby było to przydatne dla czegokolwiek innego niż adres „podwójnej pętli zwrotnej”
::ffff:127.0.0.1
. Jest to najprawdopodobniej najlepsze rozwiązanie dla większości ludzi, wiążące się tylko z pętlą zwrotną, ale umożliwiające połączenia zarówno IPv4, jak i IPv6.Czy muszę zmodyfikować plik hosts?
NO . Nie modyfikuj pliku hosts. Program rozpoznawania nazw DNS wie, co z tym zrobić
localhost
, przedefiniowanie go w najlepszym wypadku nie przyniesie żadnego efektu, aw najgorszym przypadku zmyli piekło z usług tłumacza.Co
--skip-name-resolve
?Może to również rozwiązać problem z pokrewnego, ale nieco innego powodu.
Bez tej opcji konfiguracji MySQL będzie próbował rozwiązać wszystkie adresy IP połączeń klienta z nazwą hosta za pomocą
PTR
zapytania DNS. Jeśli Twój serwer MySQL jest już włączony do korzystania z IPv6, ale połączenia wciąż trwają długo, może to być spowodowane tym, że odwrotnyPTR
rekord DNS ( ) nie jest poprawnie skonfigurowany.Wyłączenie rozpoznawania nazw rozwiąże ten problem, ale wiąże się z innymi konsekwencjami, w szczególności że wszelkie uprawnienia dostępu skonfigurowane do używania nazwy DNS w tym
Host
stanie nie będą działać.Jeśli masz zamiar to zrobić, musisz skonfigurować wszystkie granty, aby używały adresów IP zamiast nazw.
źródło
::1
. Niestety::ffff:127.0.0.1
nadal dawał mi 1 sekundowe opóźnienie (niezależnie od użyciaskip-name-resolve
lub nie), jakieś pomysły, dlaczego? (w systemie Windows 8.1)Zwykle, gdy IPv6 jest włączony na serwerze, połączenia z MySQL
localhost
są bardzo wolne.Zmiana adresu serwera mysql w skrypcie, aby
127.0.0.1
rozwiązać problem.źródło
localhost
do resolvera DNS z tego powodu, że @DaveRandom połączył się z: serverfault.com/questions/4689localhost
. Miałem ten sam problem z opóźnieniem adresu serwera w formularzuxx.xxxx.xxxxx.xxxxx.com
. Gdy zmieniłem nazwę serwera na adres IP, problem zniknął.Cóż, to całkiem oczywiste, jaki jest tego powód. PHP jest naprawdę dobry w niektórych sprawach, ale nie w bezpośrednim tłumaczeniu „localhost” na „127.0.0.1”. Musisz spróbować, to naprawdę obniży ogólny czas ładowania strony, ponieważ powstrzymuje PHP przed sprawdzaniem pliku HOSTS i co nie robi, aby uzyskać prawdziwy adres IP za „localhost”
źródło
Dodanie tego wiersza do pliku hosts rozwiązało problem
Szczegółową odpowiedź można znaleźć w tym wątku: /programming/13584360/php-with-mysql-is-slow
źródło
Możesz także wyeliminować spowolnienie zapytania, dokonując niewielkiej korekty zmiennej połączenia db (która, mam nadzieję, znajduje się w oddzielnym pliku od skryptów w celu zapewnienia przenośności). Zmień wartość hosta na „127.0.0.1” zamiast „localhost”. Pomija to długie wyszukiwanie DNS dla hosta lokalnego.
Mam nadzieję że to pomoże!
źródło