"Ошибки" программистов: MySQL server has gone away на хостинге. "Ошибки" программистов: MySQL server has gone away на хостинге Большой или некорректный пакет

Ошибка MySQL Server Has Gone Away (error 2006) может возникнуть в двух случаях.

Таймаут соединения

Наиболее распространенная проблема: таймаут соединения, в результате чего сервер его закрывает. Решение весьма тривиальное — увеличение лимита времени wait_timeout в файле конфигурации my.cnf . Для этого в Debian нужно выполнить:

Sudo nano /etc/mysql/my.cnf

# Открытие файла настроек MySQL

Затем установить тайм-аут ожидания:

Wait_timeout = 600

# Время ожидания в секундах, можно установить вплоть до 28800 с (8 часов)

Не забудьте перезагрузить базу:

Sudo /etc/init.d/mysql restart

Иногда, при выполнении длительных запланированных задач, также может появиться ошибка MySQL Server Has Gone Away все из-за того же таймаута соединения. При этом лимит времени не получится существенно увеличить (максимум до нескольких часов), так как это может привести к заполнению буфера ожидающими соединениями.

Поэтому лучше проверить соединение и, при необходимости, переподключиться.

$link = mysql_connect("localhost","root","root"); # Здесь будут cron jobs if(!mysql_ping($link)) $link = mysql_connect("localhost","root","root", true);

# Подключение БД и переподключение при необходимости

Большой или некорректный пакет

Вторая распространенная проблема: сервер получает большой или некорректный пакет и отклоняет его. В этом случае сервер считает, что проблема на стороне клиента и закрывает соединение. Так что для решения нужно увеличить лимит на максимальный размер пакета все в том же файле конфигурации:

Max_allowed_packet = 64M …

# Увеличение лимита размера входящего пакета, в МБ

Также не забудьте перезагрузить базу данных.

Самое главное

После того, как устраните ошибку MySQL Server Has Gone Away, поиграйтесь с параметрами wait_timeout и max_allowed_packet для получения оптимальных лимитов.

Случается так, что разработчики на PHP встречаются с ошибкой, когда сервер баз данных MySQL при выполнении скриптов неожиданно "падает", выдавая ошибку с сообщением: "ERROR 2006 (HY000): MySQL server has gone away ". Сегодня мы разберем один из вариантов (или сценариев), когда это случается.

Один из клиентов нашего обратился к нам с подобной ошибкой с просьбой "объснить", почему такое происходит и почему "у нас ложится сервер?". Вследствии обработки его запроса выяснилось, что у клиента на одном из проектов выполнялся скрипт, который в течении 3 минут собирал статистику или ждал получение ответа от внешнего (стороннего) хоста, а затем скрипт должен был "положить" этот ответ в базу данных, т.е. сохранить этот ответ в заданной таблице.

При выполнении скрипта использовался примерно такой цикл, в котором делалась пауза в выполнении скрипта на 30 секунд:

// здесь уже должен быть ключ для извлечения результатов проверки текста на уникальность! $counter = 4; while ($counter > 0) { sleep(30) ; $checkResults = $plagiarism->getTextCheckResults($textUid); if ($checkResults instanceof \common\components\plagiarism\Text && $checkResults->

Т.е. скрипт пытался протестировать текст на уникальность за счет внешнего сервиса и делал 4 попытки через каждые 30 секунд. Однако когда скрипт уже получал успешный отклик от внешнего хоста в результатами, и пытался сохранить эти результаты в базы данных, вылезала подлая ошибка:

2016-01-30 22:32:05 exception "yii\base\Exception" with message "SQLSTATE: General error: 2006 MySQL server has gone away The SQL being executed was: SELECT * FROM `plagiarism` WHERE text_uid = "56ad0f99425bc"" in /home/mysite.ru/modules/client/controllers/CompanyController.php:150

Было очень много эмоций с самого разработчика, потому что по всем ожиданиям такого не должно было случиться!

Однако решенеи лежало под носом, и дело лишь заключалось в том, чтобы обратить внимание на значение одной глобальной серверной переменной MySQL, а именно на значение переменной connect_timeout = 10 (в секундах), которая отвечает за таймаут коннекта с MySQL-сервером. Т.е. если в течение этих 10 секунд работающий скрипт не пытается взаимодействовать с MySQL-сервером, это соединение рвется и его необходимо устанавливать заново !

Теперь вы понимаете, как надо изменить этот участок кода: нужно уменьшить время sleep(30) до значения, не превосхожящее 10 секунд . И - вуаля! Теперь все работает, как и ожидалось!

// здесь уже должен быть ключ для извлечения результатов проверки текста на уникальность! $counter = 10; while ($counter > 0) { sleep(9) ; // здесь происходит также сохранение полученного результат в БД! $checkResults = $plagiarism->getTextCheckResults($textUid); if ($checkResults instanceof \common\components\plagiarism\Text && $checkResults->check_result !== null) { break; } --$counter; }

Так что обращайте, пожалуйста, внмиание на такие вещи, потому что они совершенно не очевидны, и задумывайтесь о логике работы ваших скриптов в заданных конкретных условиях

В логах ошибок PHP иногда можно встретить записи типа MySQL Server Has Gone Away (error 2006). Они означают, что соединение с сервером баз данных (ожидание сессии) прервалось по таймауту. Ошибку можно легко исправить.

Как исправить ошибку MySQL Server Has Gone Away

Ошибка MySQL Server Has Gone Away (error 2006) может возникнуть в двух случаях:

  1. Соединение с MYSQL прерывается по таймауту, передача данных не успевает завершится в рамках сессии.
  2. Пакет, который передается слишком большой или некорректный

Быстрым решением является увеличение значений двух глобальных переменных MySQL. Делается это в основном конфигурационном файле сервера баз данных /etc/mysql/my.cnf или в консоли MySQL авторизовавшись как root

В консоли это выглядит так:

set @@GLOBAL.max_allowed_packet=96000000;
set @@GLOBAL.wait_timeout=1000;

Решение с внесением изменений в файл /etc/mysql/my.cnf.

ВАРИАНТ 1 — Таймаут соединения С БД

Программный код может делать запрос в базу данных, который обрабатывается больше максимального времени выполнения запроса, установленного в конфигурационном файле. При этом срабатывает ограничение на время ожидания в сессии.

Лучше всего выяснить почему такие запросы имеют место и оптимизировать их, но для того чтобы получить мгновенный результат нужно увеличить значение параметра wait_timeout . Значение задается в секундах и не может быть более 28800.

mcedit /etc/mysql/my.cnf

wait_timeout = 1000

После внесения любых изменений в конфигурационный файл перезапускаем MySQL

/etc/init.d/mysql restart

ВАРИАНТ 2 — СЛИШКОМ Большой пакет

Несколько другая ситуация имеет место когда сервер отклоняет пакет из-за его слишком большого размера (или в случае если сервер не может распознать пакет по той или иной причине). В логи при этом пишутся точно такие же сообщения.

Решение в этом случае практически такое же — необходимо скорректировать значение одной переменной в конфигурационном файле.

mcedit /etc/mysql/my.cnf


max_allowed_packet = 96M

В примере задан максимальный размер пакета, который сервер не будет отвергать — 96 Мб. Устанавливать слишком большие значения не стоит.

Также перезапускаем MySQL

/etc/init.d/mysql restart

Таким образом, РНР ошибка mysql server has gone away в большинстве случаев побеждается корректировкой значений двух переменных и перезапуском сервера баз данных.


Все изложенное в данном разделе относится также и к родственной ошибке Lost connection to server during query .

Наиболее часто ошибка MySQL server has gone away возникает в результате тайм-аута соединения и его закрытия сервером. По умолчанию сервер закрывает соединение по прошествии 8 часов бездействия. Можно изменить лимит времени, установив при запуске mysqld переменную wait_timeout .

Другой распространенной причиной получения ошибки MySQL server has gone away является выдача команды "закрытия" на соединении MySQL с последующей попыткой выполнить запрос на закрытом соединении.

Если это получено в скрипте, то достаточно просто повторить запрос от клиента, чтобы соединение автоматически восстановилось.

Обычно в этом случае выдаются следующие коды ошибки (какой из них вы получите, зависит от ОС):

Ошибка будет также выдана, если кто-нибудь уничтожит выполняющийся поток посредством kill номерпотока.

Проверить, что MySQL на ходу, можно, запустив mysqladmin version и изучив время работы (uptime). Если проблема в аварийном завершении mysqld , то необходимо сосредоточиться на поиске причины аварии. В этом случае следует сначала проверить, не будет ли уничтожен MySQL снова при повторном задании запроса ().

Эти ошибки будут также выдаваться при посылке серверу неверного или слишком длинного запроса. Если mysqld получает неправильный или слишком большой пакет, то сервер предполагает, что с клиентом что-то не так, и закрывает соединение. Если необходимо выполнять объемные запросы (например, при работе с большими столбцами типа BLOB), можно увеличить предельный размер запроса, запустив mysqld с опцией -O max_allowed_packet=# (по умолчанию 1 Mb). Дополнительная память выделяется по требованию, так что mysqld будет выделять больше памяти только в случае, когда выдан большой запрос или когда mysqld должен возвратить большую строку результата!

Вы также можете получить разрыв соединения, если вы отправили пакет больше 16Mb, если ваш клиент старше чем 4.0.8, а ваш сервер 4.0.8 или новее.

Если у вас возникнет желание сделать отчет об ошибке по этой проблеме, то не забудьте включить в него следующие сведения:

    Информацию о том, упал MySQL или нет (это можно определить по файлу hostname.err ().

    Если определенный запрос уничтожает mysqld , а используемые в нем таблицы перед выполнением запроса проверялись с помощью CHECK TABLE , то желательно составить контрольный тест ().

    Значение переменной wait_timeout в сервере (это значение выдает mysqladmin variables).

    Информацию о том, пробовали ли вы запускать mysqld с --log и проверять, появляется ли выданный запрос в журнале.

Ошибка MySQL Server Has Gone Away (error 2006) может возникнуть в двух случаях.

Таймаут соединения

Наиболее распространенная проблема: таймаут соединения, в результате чего сервер его закрывает. Решение весьма тривиальное — увеличение лимита времени wait_timeout в файле конфигурации my.cnf . Для этого в Debian нужно выполнить:

Sudo nano /etc/mysql/my.cnf

# Открытие файла настроек MySQL

Затем установить тайм-аут ожидания:

Wait_timeout = 600

# Время ожидания в секундах, можно установить вплоть до 28800 с (8 часов)

Не забудьте перезагрузить базу:

Sudo /etc/init.d/mysql restart

Иногда, при выполнении длительных запланированных задач, также может появиться ошибка MySQL Server Has Gone Away все из-за того же таймаута соединения. При этом лимит времени не получится существенно увеличить (максимум до нескольких часов), так как это может привести к заполнению буфера ожидающими соединениями.

Поэтому лучше проверить соединение и, при необходимости, переподключиться.

$link = mysql_connect("localhost","root","root"); # Здесь будут cron jobs if(!mysql_ping($link)) $link = mysql_connect("localhost","root","root", true);

# Подключение БД и переподключение при необходимости

Большой или некорректный пакет

Вторая распространенная проблема: сервер получает большой или некорректный пакет и отклоняет его. В этом случае сервер считает, что проблема на стороне клиента и закрывает соединение. Так что для решения нужно увеличить лимит на максимальный размер пакета все в том же файле конфигурации:

Max_allowed_packet = 64M …

# Увеличение лимита размера входящего пакета, в МБ

Также не забудьте перезагрузить базу данных.

Самое главное

После того, как устраните ошибку MySQL Server Has Gone Away, поиграйтесь с параметрами wait_timeout и max_allowed_packet для получения оптимальных лимитов.