Рассмотрим, как исправить ошибку MySQL server has gone away (error 2006), которая появляется при обращении к сервису MySQL.
Наиболее распространение причины ошибки MySQL server has gone away:
- Слишком большой размер пакета в запросе к MySQL (по умолчанию максимальный размер — 16 Мб);
- Закончилась свободная оперативная память (RAM) на сервере MySQL (проверить свободную память в Linux можно с помощью команды free –h)
- Неактивное соединение между вашим приложением и MySQL (по умолчанию сессия разрывается через 8 часов).
General error: 2006 MySQL server has gone away
Error Code: 2013. Lost connection to MySQL server during query
PDOException: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Чтобы увеличить таймаут для подключений к MySQL, нужно добавить следующие опции в конфигурационный файл mysqld.cnf:
sudo nano /etc/mysql/my.cnf
Найдите секцию [mysqld] и увеличьте таймаут до 24 часов:
wait_timeout = 86400 interactive_timeout = 86400
Если вы загружаете в MySQL большие файлы или BLOB объекты более 16 Мб, то MySQL с настройками по-умолчанию также может вернуть ошибку MySQL server has gone away. Нужно увеличить максимальный размер пакета в my.cnf.
Для этого в секции [mysqld] увеличьте значение параметра max_allowed_packet со стандартного 16M до 128MB:
max_allowed_packet = 128MB
После внесения изменений в файл mysqld.cnf нужно перезапустить сервис MySQL:
- В CentOS/RHEL:
sudo systemctl restart mysqld - В Ubuntu:
sudo systemctl restart mysql.service
Если вы подключаетесь к MySQL из PHP, проверьте что значения таймаутов в php.ini больше, чем в MySQL
mysql.connect_timeout=86400 mysql.allow_persistent=1
Эта ошибка означает, что MySQL сервер запущен, но он отказывает вам в соединении. Это может произойти по нескольким причинам. Самых основных и часто встречающихся причин три: сервер перегружен, и у вас истекло время ожидания ответа, ваш клиент отправил слишком большой пакет или сервер был не до конца проинициализирован.
В этой небольшой статье мы рассмотрим более подробно, почему возникает ошибка 2006: MySQL server has gone away, а также — как её исправить.
Такую ошибку вы можете увидеть во время подключения к базе данных с помощью PHP, консольного клиента или, например, в PhpMyAdmin:
1. Истекло время ожидания
Как я уже писал выше, одной из причин может быть таймаут ожидания соединения. Возможно, сервер баз данных перегружен и не успевает обрабатывать все соединения. Вы можете подключиться к серверу с помощью консольного клиента, если вам это удастся, и попытаться выполнить какой-либо запрос, чтобы понять, действительно ли запросы выполняются слишком долго. Если это так, можно оптимизировать производительность MySQL с помощью скрипта MySQLTuner.
В большинстве случаев надо увеличить размер пула движка InnoDB с помощью параметра innodb_buffer_pool_size. Какое значение лучше поставить, можно узнать с помощью указанного выше скрипта. Например, 800 мегабайт:
sudo vi /etc/mysql/my.cnf
innodb_buffer_pool_size=800M
Есть и другой путь решения этой проблемы. Если такая скорость обработки запросов считается нормальной, можно увеличить время ожидания ответа от сервера. Для этого измените значение параметра wait_timeout. Это время в секундах, на протяжении которого надо ждать ответа от сервера. Например:
wait_timeout=600
После любых изменений не забудьте перезапустить MySQL сервер:
sudo systemctl restart mysql
или:
sudo systemctl restart mariadb
2. Слишком большой пакет
Если ваш клиент MySQL создаёт слишком большие пакеты с запросами к серверу, это тоже может стать причиной такой ошибки. Максимально доступный размер пакета можно увеличить с помощью параметра max_allowed_packet. Например:
sudo vi /etc/mysql/my.cnf
max_allowed_packet=128M
Обратите внимание, что если вы из своей программы отправляете большие пакеты, то, скорее всего, вы делаете что-то не так. Не надо генерировать запросы к MySQL с помощью циклов for. SQL — это отдельный язык программирования, который многое может сделать сам, без необходимости писать очень длинные запросы.
3. Сервер неверно проинициализирован
Такая проблема может возникать при разворачивании контейнера MySQL или MariaDB в Docker. Дело в том, что на первоначальную инициализацию контейнера нужно много времени: около нескольких минут. Если вы не дадите контейнеру завершить инициализацию, а остановите его и потом снова запустите, то база данных будет всегда возвращать такую ошибку.
Вам нужно полностью удалить данные контейнера с базой данных. Например, с помощью docker-compose:
docker-compose down
или вручную:
docker rm mysql-container
Здесь mysql-container — это имя контейнера с базой данных. А затем надо удалить хранилище (volume) с некорректно проинициализированной базой. Сначала посмотрите список всех хранилищ:
docker volume ls
Затем удалите нужное:
docker volume rm имя_хранилища
После этого можете снова запускать инициализацию приложения, только на этот раз дождитесь, пока сервер баз данных сообщит, что он готов, и вы сможете к нему подключиться.
Выводы
В этой небольшой статье мы рассмотрели, что значит ошибка MySQL Server has gone away, а также как её исправить на сервере или в контейнере Docker. Вы знаете ещё другие причины и решения этой проблемы? Пишите в комментариях!
Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .
Об авторе
Основатель и администратор сайта losst.ru, увлекаюсь открытым программным обеспечением и операционной системой Linux. В качестве основной ОС сейчас использую Ubuntu. Кроме Linux, интересуюсь всем, что связано с информационными технологиями и современной наукой.

WRITE FOR US

There are only a few major cases when this happens:
1. MySQL Thread Was Killed by an Administrator or a Utility Such as pt-kill
The manual intervention is likely to be intermittent and, as it is a one-time thing in certain situations (e.g., a bad long-running query), probably would be known to a DBA. Pt-kill might be less noticeable, as it is often left running as a workaround to prevent those bad long queries from taxing system resources. Checking the system processlist should bring the commands to the surface:
|
$ ps xauf | grep pt—kill taras 6069 0.1 0.1 111416 29452 pts/29 S+ 10:57 0:00 | | _ perl /usr/bin/pt—kill —interval 1s —busy—time 5s —match—info (SELECT) h=127.0.0.1 —print —kill taras 6913 0.0 0.0 21532 1112 pts/30 S+ 11:00 0:00 | _ grep —color=auto pt—kill |
A very convenient way is to use the audit plugin available for Percona Server for MySQL to determine where the kill command came from:
|
<AUDIT_RECORD> <NAME>Query</NAME> <RECORD>624484743_2020—06—30T17:38:14</RECORD> <TIMESTAMP>2020—06—30T17:57:35 UTC</TIMESTAMP> <COMMAND_CLASS>kill</COMMAND_CLASS> <CONNECTION_ID>17</CONNECTION_ID> <STATUS>0</STATUS> <SQLTEXT>KILL QUERY 16</SQLTEXT> <USER>taras[taras] @ localhost []</USER> <HOST>localhost</HOST> <OS_USER></OS_USER> <IP></IP> <DB></DB> </AUDIT_RECORD> |
It shows the hostname, user, and time when the connection got killed.
2. Big Data Chunk Transfer
For example, when using BLOB fields to store binary data in a table or there is an INSERT statement containing a lot of rows. It may happen when using the MySQL CLI client (one of the cases being loading an SQL dump), or it can happen within an application when it tries to store the BLOB data (for example, from a file upload).
There is a limit MySQL imposes on the amount of data that can be transmitted per query, and the max_allowed_packet variable defines it.
So, in both cases, we need to determine which table the data is being written to, for instance, grepping the SQL file for INSERT INTO statements and implementing logging on the application end. This way, the statement will be stored along with the error that prevented it from completing. A partial statement can be captured (as BLOBs could be a burden to log), but as long as there is a table name, it is possible to check the table structure and see if it does contain binary data.
Example of an INSERT statement with binary data (truncated):
|
INSERT INTO t1 VALUES (1, x‘89504….82’) |
To allow for a larger query execution, the variable needs to be adjusted:
|
SET GLOBAL max_allowed_packet = 128M ; |
The variable can be set per session or globally, depending on the use case.
3. The Connection Was Closed by Timeout
It is trivial, but applications can be reusing already-established connections. During the time of inactivity or lower traffic, it is possible some connections will not be used for a while and closed on the MySQL end. It is traced best with the application logging; if there is an event that happened in the evening followed by a period of inactivity and then the error in the morning, it is very likely that MySQL closed the connection.
|
mysql> SET SESSION wait_timeout = 5 ; Query OK, 0 rows affected (0.00 sec) |
Wait for 5 seconds:
|
mysql> select 1 ; ERROR 2006 (HY000): MySQL server has gone away No connection. Trying to reconnect... Connection id: 16 Current database: *** NONE *** +—+ | 1 | +—+ | 1 | +—+ 1 row in set (0.01 sec) |
Usually, the connection is re-established, and the application continues normal operations; yet it is always possible to extend the timeout in MySQL configuration:
|
SET GLOBAL wait_timeout = 57600 ; |
The default value for the variable is 28800 seconds (8 hours), which is enough in most cases.
Also, closing connections cleanly from an application end, after a period of inactivity, eliminates this problem.
4. MySQL Server Has Actually Gone Away
This one is probably the worst possible scenario when MySQL crashes on a query or due to some other reason, e.g., the OOM killer killed the process. However, it can be caused by a clean restart, too.
In this case, one should check MySQL uptime and the logs, MySQL error log, and syslog. Those should indicate whether the server restart occurred and if there was an error leading to the restart.
In case the server did crash, it is time to find the actual cause. Check the bug tracker, as the issue might have been reported and possibly fixed already; upgrade MySQL if needed. In case it was a clean restart, check if auto-updates are enabled or if someone else restarted the service interactively (yes, lack of communication is a thing too).
Две наиболее распространенные причины получения ошибки MySQL server has gone away (error 2006) это..
- Сервер закрыл соединение по таймауту.
Исправить можно так: проверить чтобы значение переменной wait_timeout в конфиг файле MySql — my.cnf было достаточным для выполнения скрипта.
На Debian: нужно выполнитьsudo nano /etc/mysql/my.cnf
и установить wait_timeout = 600 ( значение задается в секундах, если ошибка не пропадет поиграйтесь с этим значением, чтобы найти оптимальное), после этого нужно рестартануть MySQL:
sudo /etc/init.d/mysql restart
Я не проверял, но значение по-умолчанию для wait_timeout можно установить вплоть до 28800 секунд (8 часов).
- Сервер сбрасывает (отклоняет) неправильные или слишком большие пакеты. Если mysqld получает пакет данных, который слишком большой или не корректный, он думает что что-то пошло не так или с клиентом случилась какая-то беда и закрывает соединение. Часто такая ошибка возникает при импорте дампов содержащих большие тексты.
Так же такое происходит, когда у Вас слишком большой запрос. Например, вы хотите в поле типа longtext записать какую-нибудь книгу, в которой текста на 20 мб. Либо хотите сохранить большой файл (например картинку) в поле с типом blob. В итоге у вас получается запрос по типу
UPDATE books SET text=«сууупер..длинный..текст» WHERE id=1
Если это Ваш случай, то подумайте действительно ли Вам нужно сохранять такой текст/файл в базу, обычная практика в таких случаях, сохранить его в файл на диск, а в базу сохранить имя этого файла. Типа того
file_put_content(‘book.txt’, ‘сууупер..длинный..текст’);
...
UPDATE books SET filename=«book.txt» WHERE id=1
Исправить можно так: вы можете увеличить максимальный размер пакета увеличив значение max_allowed_packet в файле my.cnf.
На Debian нужно выполнить:sudo nano /etc/mysql/my.cnf
и установить max_allowed_packet = 64M (если ошибка не пропадет поиграйтесь с этим значением, чтобы найти оптимальное), после этого нужно рестартануть MySQL
sudo /etc/init.d/mysql restart
Про max_allowed_packet я так же писал здесь: ERROR 2006 (HY000) — MySQL server has gone away
Если Вы получаете ошибку MySQL server has gone away (error 2006) при использовании драйвера MySQL ODBC – можете попробовать это решение.
Оригинал исходной статьи (на англ): How to fix “MySQL server has gone away” (error 2006)
Похожие статьи
Автор:
| Рейтинг: 5/5 |
Теги:
Ошибка 2006 под названием MySQL Sever has gone away означает отказ сервера в соединении даже при условии, что он запущен. Известно всего три причины, почему ошибка появляется. Первая причина – сервер перегружен. Время ожидания истекло. Вторая причина – клиент отправил слишком больной пакет. Третья – сервер не был до конца проинициализирован. Дальше подробно рассмотрим, по каким причинам появляется ошибка и как с ней бороться.
Как исправить ошибку
Обычно ошибка появляется при попытке подключиться к базе данных при помощи PHP, консольного клиента, а также в случае использования PhpMyAdmin:
Давайте дальше рассмотрим каждую ситуацию в отдельности.
Истекло время ожидания
Как было сказано в начале статьи, одна из возможных причин – истечение времени ожидания. Может быть так, что сервер был перегружен и не справляется с нагрузкой – обработкой всех соединений. Чтобы понять, насколько долго выполняются серверные запросы, можно воспользоваться любым консольным клиентом и подключиться к серверу. Если вам удастся это сделать, выполните любой запрос. Если на обработку запросов уходит слишком много времени, оптимизировать MySQL можно при помощи специального скрипта MySQLTuner. Обычно увеличивается размер пула движка InnoDB путем установки параметра innodb_buffer_pool_size. Оптимальное значение определяется при помои приведенного выше скрипта.
Если это 800 мегабайт (может быть и другой размер), прописываем:
$ sudo vi /etc/mysql/my.cnf
innodb_buffer_pool_size=800M
Существует и другой способ решения проблемы. Для этого увеличивают время ответа от сервера. Чтобы выполнить эту задачу, необходимо изменить параметр wait_timeout. Это время в секундах, на протяжении которого надо ждать ответа от сервера.
Например:
wait_timeout=500
Внося изменения, не забываем дальше перезагрузить сервер:
$ sudo systemctl restart mysql
или:
$ sudo systemctl restart mariadb
Слишком большой пакет
Когда клиент пользователя создает слишком большое количество пакетов, сервер выдаст именно эту ошибку. Доступный размер пакета (максимальное значение) можно увеличить с помощью параметра max_allowed_packet.
Например:
$ sudo vi /etc/mysql/my.cnf
max_allowed_packet=128M
Отдельно обратите внимание на клиент, ведь если он посылает много запросов, то вы явно что-то делает не так. Как минимум не стоит генерировать запросы к MySQL с помощью циклов for.
Сервер неверно проинициализирован
Если вы решите развернуть MySQL или MariaDB в Docker, то будьте готовы столкнуться с подобной ошибкой. Первоначальная инициализация контейнера требует чуть больше свободного времени. Если не дать контейнеру завершить инициализацию, сперва остановив его и запустив, то база данных будет всегда возвращать такую ошибку. Решение – нужно полностью удалить данные контейнера с базой данных.
Делается это так:
$ docker-compose down
или:
$ docker rm mysql-container
Дальше надо удалить хранилище (volume) с некорректно проинициализированной базой. Но в начале просмотрите список всех хранилищ:
$ docker volume ls
После удаляем:
$ docker volume rm имя_хранилища
Теперь можете запустить инициализацию приложения, только дождитесь, пока сервер баз данных сообщит, что он готов, и вы сможете к нему подключиться.











