Старый сайт на PHP 5.4 после переезда на MySQL 8: «Got packets out of order» и как его оживить
Эдгар Косулин 5 мин чтения
Серия «Хостинг без магии» · часть 16 из 16
Содержание
3 ноября мы на тестовом сервере переносили сайты на чистую установку MySQL 8.0 и проверяли, как они открываются. Один из них, WordPress на PHP 5.4, вёл себя странно. Функция mysqli_connect возвращала соединение, ошибки подключения не было. А первый же запрос падал:
Got packets out of order (1156)
Ошибка звучит как сбой сети, но сеть тут ни при чём. Старый PHP и новый MySQL по-разному понимают, как проходит вход в базу.
Почему старые сайты до сих пор на PHP 5
PHP 5.4 перестал получать обновления в сентябре 2015 года, PHP 5.2 ещё в 2011-м. Сайты на них живут потому, что работают, а переделка стоит денег. Частая причина застрять: код использует функции mysql_*, которые убрали в PHP 7.0. Переключить такой сайт на новую версию PHP одной кнопкой нельзя, он просто перестанет открываться.
На нашем хостинге почти 90 работающих сайтов на PHP 5.2 и 5.4. Поэтому версии от 5.2 до 8.5 в панели остаются, все 13. Но любой переезд для такого сайта рискованнее, чем для свежего.
Что меняется в MySQL 8
У каждого пользователя базы есть способ проверки пароля, в MySQL он называется плагином аутентификации. Много лет стандартом был mysql_native_password. В MySQL 8.0 по умолчанию стал caching_sha2_password: он надёжнее, но старые клиенты о нём не знают. В PHP 5.x его поддержки нет совсем, она появилась только в ветке 7.
На хостинге со старой базой пользователи созданы со старым способом. Когда сайт переезжает на новую установку MySQL 8, пользователей создают заново. И если ничего не настраивать, они получат новый способ по умолчанию.
Дальше всё зависит от версии PHP и драйвера. Симптомы, которые встречаются чаще всего:
Got packets out of order(1156) на первом запросе, хотя соединение «есть». Так было у нас с PHP 5.4;The server requested authentication method unknown to the client: подключение не проходит совсем, чаще у PHP 7.0–7.3;mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication: это ещё более древний случай, пароль хранился в формате до MySQL 4.1.
Где ошиблись мы
Первое, что мы сделали, выглядело логично. Перевели пользователя базы этого сайта на mysql_native_password, пароль не меняли. Ошибка осталась.
Как мы поняли, дело в самом начале соединения. Сервер ещё до проверки пароля сообщает клиенту свой способ по умолчанию. Если это caching_sha2_password, сервер потом просит клиента переключиться на старый способ, и старый драйвер PHP на этом сбивается. Поэтому одной правки пользователя не хватило. Понадобилась настройка всего сервера:
[mysqld]
default_authentication_plugin=mysql_native_password
После перезапуска MySQL тот же PHP 5.4 прочитал все 47 таблиц, и WordPress открылся как на старом сервере. Заодно мы перепроверили сайты на PHP 5.2 и 8.3: им настройка не помешала.
Была и вторая находка. При восстановлении из резервной копии наш импорт пропустил шесть баз. Пароли их пользователей лежали в копии в старом формате, и на сервере с новым способом по умолчанию такие пользователи не создавались. С той же настройкой они создаются штатно, мы проверили это на временном пользователе. Теперь она стоит в инструкции по сборке сервера до первого импорта.
Учтите одно: настройка действует только на новых пользователей. Тех, кто уже создан с caching_sha2_password, она не переключит. Их надо переводить отдельно, а пароль либо сохранить, либо сменить и сразу поправить его в конфигурации сайта.
Как проверить у себя
Если сайт после переезда пишет одну из ошибок выше, сначала узнайте, что за сервер базы. В phpMyAdmin или любом клиенте MySQL выполните:
SELECT VERSION(), @@default_authentication_plugin;
SHOW CREATE USER CURRENT_USER();
Первая строка покажет версию и способ по умолчанию, вторая покажет способ вашего пользователя (после слов IDENTIFIED WITH). Версию PHP, с которой реально работает сайт, смотрите через phpinfo() во временном файле, а не в настройках панели. После переноса режим запуска PHP мог смениться, и вместе с ним версия.
Если у вас свой VDS, лечение такое. Добавьте настройку выше в конфигурацию MySQL (на CentOS и AlmaLinux это файл в /etc/my.cnf.d/, на Debian и Ubuntu в /etc/mysql/conf.d/), проверьте её и перезапустите сервер (на Debian и Ubuntu служба называется mysql):
mysqld --validate-config
systemctl restart mysqld
Пользователя сайта переведите на старый способ:
ALTER USER 'site'@'localhost' IDENTIFIED WITH mysql_native_password BY 'новый-пароль';
Пароль потом впишите в конфигурацию сайта. Остальных пользователей вслепую не трогайте, особенно служебных.
На виртуальном хостинге настройки сервера вам недоступны. Напишите в поддержку, какая ошибка и на какой версии PHP сайт. Если хостинг не может вернуть старый способ по умолчанию, остаётся выбор: другой хостинг, свой VDS или обновление сайта.
Ещё одна ловушка: расширения не подгрузились
С тем же старым PHP бывает и другая беда, тоже после переезда. Сайт пишет, что нет функции mysql_connect или расширения JSON, хотя в панели всё включено.
Мы видели это на сайтах, где PHP запускается в режиме CGI. Панель передаёт старому PHP список папок с настройками через двоеточие, а PHP до версии 5.5.10 такой записи не понимает (ошибка #66574). В итоге он не читает файл, где включены расширения, и остаётся с набором по умолчанию. На одном старом сайте Joomla вместо 80 расширений грузилось 33, и ни одного для MySQL.
Своими силами это не чинится: исправление нужно в настройках сервера. Если видите такое у себя, напишите в поддержку, указав версию PHP и режим запуска.
Как это устроено на Siteko. На хостинге работает MySQL 8.0 со способом входа
mysql_native_passwordпо умолчанию, поэтому сайты на PHP 5.x подключаются к базе. Версию PHP от 5.2 до 8.5 вы выбираете в панели для каждого сайта. Перенос сайта к нам поддержка делает сама и бесплатно, заодно проверим, что старый сайт открывается.
Почему это временная мера
Возврат старого способа входа продлевает сайту жизнь, но не решает задачу. В MySQL 8.0 mysql_native_password уже объявлен устаревшим, в MySQL 8.4 он выключен по умолчанию, в 9.0 его убрали совсем. Рано или поздно хостинг обновит базу, и этот мост исчезнет.
PHP 5.4 не получает исправлений безопасности одиннадцать лет. Старые CMS на нём чаще других взламывают через давно известные дыры. Если сайт нужен бизнесу, следующий шаг - план обновления: перевод кода с mysql_* на mysqli или PDO, новая версия CMS, PHP 8. Как обновлять сайт и не сломать его, мы разобрали в статье Как обновлять CMS и плагины и не сломать сайт. Что ещё проверить после переезда, есть в статьях Переезд на другой хостинг без потери сайта, писем и заказов и Ошибка 500 после загрузки сайта.
Серия
Хостинг без магии
- 1. Как выбрать хостинг для сайта и не купить себе вторую работу
- 2. Виртуальный хостинг, VPS или облако: что действительно нужно вашему сайту
- 3. Гигабайты ничего не решают: как читать характеристики тарифа хостинга
- 4. «Безлимитный» хостинг: что заканчивается раньше дискового пространства
- 5. Домен подключён, а сайт не открывается: DNS без мистики
- 6. HTTPS включён, а браузер всё равно ругается: SSL без паники
- 7. Письма с сайта пропадают: SMTP, SPF, DKIM и DMARC на пальцах
- 8. Современный PHP-хостинг: зачем Laravel и Symfony нужны SSH, Composer, Node.js, cron и отдельная public-директория
- 9. Деплой без FTP на виртуальном хостинге: Git, Composer и безопасный откат
- 10. Ошибка 500 после загрузки сайта: где искать причину до обращения в поддержку
- 11. Сайт тормозит на хостинге: виноват тариф, код, база или внешний сервис
- 12. Бэкап есть, восстановить нельзя: проверяем резервные копии до аварии
- 13. Переезд на другой хостинг без потери сайта, писем и заказов
- 14. Когда виртуальный хостинг стал тесен: пора на VPS или ещё можно остаться
- 15. Коды подтверждения не приходят на почту: лимит отправки писем на хостинге
- 16. Старый сайт на PHP 5.4 после переезда на MySQL 8: «Got packets out of order» и как его оживить
Новые статьи и разборы — в канале Siteko: Telegram MAX
Подписчикам: +30 дней к пробному хостингу, клиентам: +150 ₽ на баланс