Я только что установил новый XAMPP. При первом открытии PHPMyAdmin я заметил, что он работает очень медленно. Не имело смысла, что на локальном хосте открытие каждой страницы должно занимать почти 5 секунд. Я сделал небольшой тестовый пример, чтобы снять вину с 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);
Вышеупомянутый скрипт запускается всего за 3 секунды (хотя при первом запуске мне потребовалось около 8 секунд).
Затем, чтобы проверить, была ли это ошибка PDO, я попытался использовать mysql_connect
вместо:
$con = mysql_connect("localhost", "root", "");
mysql_select_db("mysql", $con);
$result = mysql_query('SELECT host,user,password FROM user;');
На завершение уходит ровно столько же времени.
Сначала я думал, что это ошибка PHP, но код PHP и статические файлы обслуживаются быстрее, чем я могу нажать кнопку «Обновить». Я протестировал PHP, запустив этот небольшой скрипт:
header("Content-Type: text/plain");
for($i = 0; $i < 5000; $i++)
{
echo sha1(rand()) . "\n";
}
5000 sha1
вычислений, и страница по-прежнему отображается быстрее, чем я могу обновить свое окно.
Потом я решил, что это вина MySQL. Но опять же, не потребовалось много тестов, чтобы понять, что MySQL работает быстрее, чем мне нужно. Используя клиент MySQL CLI, запрос выбора пользователя даже не занимает измеримого времени - он выполняется до того, как я даже отпущу клавишу возврата.
Проблема, должно быть, связана с подключением PHP к MySQL - это, насколько я могу понять. Я могу найти массу материалов о медленном PHP или MySQL, но ничего о том, что PHP + MySQL очень медленный.
Спасибо всем, кто может помочь мне решить эту проблему!
Я использую XAMPP 1.8.0 для win32 (Ссылка на скачивание)
Версия PHP: 5.4.4
Версия MySQL: 14.14
РЕДАКТИРОВАТЬ: по истечении времени оказывается, что функция подключения занимает так много времени:
$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);
Вывод:
Connect time: 1.006148 Query time: 0.000247
Что может заставить PHP тратить много времени на подключение к базе данных? Клиент CLI, HeidiSQL и рабочая среда MySQL мгновенно подключаются
Это почти дословно взято из моего ответа Вот, но я знаю, что мы неодобрительно относимся к ответам только по ссылкам на SO, поэтому я полагаю, что вы, ребята, тоже :-)
Если у вас возникла эта проблема и вы используете версию Windows до Windows 7, вероятно, это не решение вашей проблемы.
Почему это происходит?
Причина этой проблемы - IPv4 против IPv6.
Когда вы используете имя хоста вместо IP-адреса, клиент MySQL сначала запускает AAAA
(IPv6) ищет имя узла и сначала пытается использовать этот адрес, если он успешно разрешает имя в адрес IPv6. Если какой-либо шаг завершится неудачно (разрешение имени или соединение), он вернется к IPv4, запустив A
искать и вместо этого пробовать этот хост.
На практике это означает, что если IPv6 localhost
поиск успешен, но MySQL не привязан к петле IPv6, вам нужно подождать один цикл тайм-аута подключения, прежде чем произойдет откат IPv4 и соединение будет успешным.
До Windows 7 это не было проблемой, потому что localhost
разрешение было выполнено через файл hosts, и оно было предварительно настроено только с 127.0.0.1
- он не поставлялся со своим аналогом IPv6 ::1
.
Однако с Windows 7 localhost
разрешение встроено в преобразователь DNS по указанным причинам Вот. Это означает, что поиск IPv6 теперь будет успешным, но MySQL не привязан к этому IPv6-адресу, поэтому соединение не удастся, и вы увидите задержку, указанную в этом вопросе.
Это мило. Подскажите уже как исправить!
У вас есть несколько вариантов. Если заглянуть в Интернет, то общее «решение», похоже, состоит в том, чтобы явно использовать IP-адрес вместо имени, но есть несколько причин не делать этого, обе связаны с переносимостью, и обе, возможно, не важны:
Если вы переместите свой скрипт на другую машину, только поддерживает IPv6, ваш скрипт больше не будет работать.
Если вы переместите свой скрипт в среду хостинга на основе * nix, волшебная строка localhost
будет означать, что клиент MySQL предпочел бы использовать сокет Unix, если он настроен, это более эффективно, чем подключение на основе обратной петли IP
Они кажутся довольно важными?
Это не так. Вы должны разрабатывать свое приложение так, чтобы подобные вещи определялись в файле конфигурации. Если вы переместите свой сценарий в другую среду, скорее всего, потребуется настроить и другие вещи.
Таким образом, использование IP-адреса не является Лучший решение, но, скорее всего, приемлемое.
Так какое же лучшее решение?
Лучшим способом было бы изменить адрес привязки, который использует сервер MySQL. Однако это не так просто, как хотелось бы. В отличие от Apache, Nginx и почти всех других когда-либо созданных нормальных приложений сетевых служб, MySQL поддерживает только один адрес привязки, так что это не просто случай добавления еще одного. К счастью, операционные системы поддерживают здесь немного магии, поэтому мы можем позволить MySQL использовать как IPv4, так и IPv6 одновременно.
Вам необходимо запустить MySQL 5.5.3 или новее, и вам нужно запустить MySQL с --bind-address=
аргумент командной строки. У вас есть 4 вариантадокументы, в зависимости от того, что вы хотите сделать:
Тот, с которым вы, вероятно, знакомы, и тот, который вы, скорее всего, (эффективно) используете, 0.0.0.0
. Это привязывается ко всем доступным IPv4-адресам на машине. На самом деле, вероятно, это не лучший вариант, даже если вас не волнует IPv6, поскольку он подвержен тем же рискам безопасности, что и ::
.
Явный адрес IPv4 или IPv6 (например, 127.0.0.1
или ::1
для петли). Это привязывает сервер к этому адресу и только этот адрес.
Волшебная струна ::
. Это свяжет MySQL со всеми адресами на машине, как с адресами обратной связи, так и с адресами физического интерфейса, в режимах IPv4 и IPv6. Это потенциально угроза безопасности, делайте это только в том случае, если вам нужно, чтобы MySQL принимал соединения с удаленных хостов.
Используйте IPv4-сопоставленный IPv6-адрес. Это специальный механизм, встроенный в IPv6 для обратной совместимости во время перехода 4 -> 6, и он позволяет выполнять привязку к конкретному адресу IPv4 и его эквиваленту IPv6. Маловероятно, что это будет полезно для чего-либо, кроме адреса «двойной петли». ::ffff:127.0.0.1
. Скорее всего, это лучшее решение для большинства людей, только привязка к обратной петле, но позволяющая соединения IPv4 и IPv6.
Мне нужно изменить файл hosts?
Нет. Не изменяйте файл hosts. Преобразователь DNS знает, что делать с localhost
, его переопределение в лучшем случае не даст никакого эффекта, а в худшем запутает распознаватель.
Что о --skip-name-resolve
?
Это также может решить проблему по связанной, но немного другой причине.
Без этой опции конфигурации MySQL будет пытаться преобразовать все IP-адреса клиентских подключений в имя хоста через PTR
DNS-запрос. Если ваш сервер MySQL уже поддерживает использование IPv6, но соединения по-прежнему занимают много времени, это может быть связано с тем, что обратный DNS (PTR
) запись настроена неправильно.
Отключение разрешения имен решит эту проблему, но у нее есть другие разветвления, в частности, любые разрешения доступа, настроенные на использование DNS-имени в Host
состояние теперь не работает.
Если вы собираетесь это сделать, вам нужно будет настроить все ваши гранты на использование IP-адресов вместо имен.
Может ли быть так, что ваш mysql пытается запускать запрос rev-dns при каждом подключении? попробуйте добавить в my.cnf раздел mysqld: пропустить имя-разрешение.
Обычно, когда IPv6 включен в соединениях сервера с MySQL, используя localhost
очень медленные.
Изменение адреса сервера mysql в скрипте на 127.0.0.1
решает вопрос.
mysql_connect("localhost", "root", "");
Что ж, вполне очевидно, в чем причина. PHP действительно хорош в некоторых вещах, но не в прямом переводе «localhost» в «127.0.0.1». Вы должны попробовать это, это действительно снизит общее время загрузки страницы вашего веб-сайта, потому что это удерживает PHP от проверки вашего файла HOSTS и того, что он не делает, чтобы получить реальный IP-адрес за 'localhost'
Добавление этой строки в ваш файл hosts решило проблему для меня
127.0.0.1 localhost
Подробный ответ можно найти в этой теме: https://stackoverflow.com/questions/13584360/php-with-mysql-is-slow
Вы также можете избежать замедления запросов, внеся небольшую корректировку в переменную подключения к базе данных (которая, надеюсь, находится в отдельном файле из ваших скриптов для переносимости). Измените значение хоста на 127.0.0.1 вместо localhost. Это позволяет избежать длительного поиска в DNS для поиска localhost.
Надеюсь это поможет!