Ошибка разрыва соединения с БД

Вы можете увидеть ошибку Lost connection to MySQL server не только по причине слишком маленького connect_timeout, но и по ряду других причин. В настоящей статье мы рассмотрим эти причины.

$php phpconf2009_4.phpstring(44) "Lost connection to MySQL server during query"
Version: '5.1.39' socket: '/tmp/mysql_sandbox5139.sock' port: 5139 MySQL Community Server (GPL)091002 14:56:54 - mysqld got signal 11 

Мы видим, что MySQL сервер упал по причине системной ошибки 11 ( mysqld got signal 11).
То есть MySQL сервер запросил у операционной системы ресурс (например, доступ к файлу или оперативной памяти), но получил отказ с кодом 11.
Эта ошибка чаще всего обозначает Segmentation fault - отказ в доступе к оперативной памяти.

Номера ошибок операционной системы не универсальны и могут отличаться.
Если вы хотите быть уверены, что данный код имеет в вашей операционной системе определённое значение или вам встретилась менее распространённая ошибка используйте утилиту perror, которая находится в директории bin директории куда вы установили MySQL.

Вот, например, что показывает perror для моей инсталляции:

$perror 11OS error code 11: Resource deadlock avoided

Далее мы видим backtrace (начиная с Attempting backtrace.) Мы вернёмся к backtace позже.
Ещё ниже мы видим запрос, который вызвал эту проблему:

Trying to get some variables.Some pointers may be invalid and cause the dump to abort...thd->query at 0x6a39e60 = select 1 from `t1` where `c0` <> (select geometrycollectionfromwkb(`c3`) from `t1`)

Проблема в запросе:

select 1 from `t1` where `c0` <> (select geometrycollection from wkb(`c3`) from `t1`)

Попытаемся воспроизвести в mysql cli:

$./my sqlmysql [localhost] {msandbox} ((none)) > use testDatabase changedmysql [localhost] {msandbox} (test) > select 1 from `t1` where `c0` <> (select geometrycollection from wkb(`c3`) from `t1`);
ERROR 2013 (HY000): Lost connection to MySQL server during querymysql [localhost] {msandbox} (test) > \qBye

То есть это регулярно повторяющийся баг. Нужно изменить приложение таким образом, чтобы оно не сталкивалось с этим багом пока он не будет исправлен.
Для этого посмотрим backtrace:

/users/ssmirnova/blade12/5.1.39/bin/mysqld(_ZN14Item_subselect4execEv+0x26)[0x595d96]/users/ssmirnova/blade12/5.1.39/bin/mysqld(_ZN24Item_singlerow_subselect8val_realEv+0xd)[0x595fbd]/users/ssmirnova/blade12/5.1.39/bin/mysqld(_ZN14Arg_comparator18compare_real_fixedEv+0x39)[0x561b89]/users/ssmirnova/blade12/5.1.39/bin/mysqld(_ZN12Item_func_ne7val_intEv+0x23)[0x568fb3]/users/ssmirnova/blade12/5.1.39/bin/mysqld(_ZN4JOIN8optimizeEv+0x12ef)[0x65208f]

Он содержит следующие вызовы: Item_subselect и Item_singlerow_subselect.
Отсюда даже не заглядывая в код MySQL мы можем сделать вывод, что виноват подзапрос. Попробуем переписать запрос:

$./my sqlmysql [localhost] {msandbox} (test) > select 1 from `t1` where `c0` <> geometrycollectionfromwkb(`c3`);Empty set (0.00 sec)

MySQL сервер работает нормально! Мы можем пользоваться переписанным запросом до тех пор, пока баг не будет исправлен.

Всегда используйте error log

Но иногда в error log нет нужной информации.

091002 16:49:48 - mysqld got signal 10 ;This could be because you hit a bug. It is also possible that this binaryor one of the libraries it was linked against is corrupt, improperly built,or misconfigured. This error can also be caused by malfunctioning hardware.We will try our best to scrape up some info that will hopefully help diagnosethe problem, but since we have already crashed, something is definitely wrongand this may fail.key_buffer_size=8384512read_buffer_size=131072max_used_connections=1max_connections=100threads_connected=1It is possible that mysqld could use up tokey_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = 225784 K

Как видим, ни backtrace, ни запроса в error log нет. Что же делать?

В этом случае, как и раньше, нам поможет general query log. MySQL сначала пишет запрос в general query log и только потом выполняет его.
Поэтому вполне логично использовать этот метод для повторяющихся проблемных запросов.

mysql> set global general_log=1;Query OK, 0 rows affected (0.00 sec)mysql> set global log_output='table';Query OK, 0 rows affected (0.00 sec)

Запускаем тест. После перезапуска сервера проверяем general query log:

mysql> select argument from mysql.general_log order by event_time desc limit 10;+--------------------------------------------+| argument                  |+--------------------------------------------+| Access denied for user 'MySQL_Instance_Manager'@'localhost' (using password: YES)               || select 1 from `t1` where `c0` <> (select geometrycollectionfromwkb(`c3`) from `t1`) |

Запрос, вызвавший крушение, обнаружен.

Используйте general query log

Если error log не содержит информации о причинах крушения сервера.
При использовании этого приёма существует вероятность, что таблица mysql.general_log будет повреждена во время крушения MySQL сервера. В этом случае попробуйте запись в файл.

Также существует вероятность, что MySQL сервер перестанет работать во время записи запроса в general query log. В таком случае пользуйтесь либо логами вашего приложения, либо прокси.

Пример, который мы только что рассмотрели, произошёл из бага MySQL сервера. Но MySQL сервер может быть аварийно остановлен и по причине нехватки ресурсов в системе.

Первое, на что стоит обратить внимание это RAM

Цитата из реального лога:

key_buffer_size=235929600read_buffer_size=4190208max_used_connections=17max_connections=2048threads_connected=13It is possible that mysqld could use up tokey_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = 21193712 K-----21193712K ~= 20G

То есть MySQL может использовать до 20G RAM! Сейчас мощные машины, но стоит проверить действительно ли у вас 20G RAM.

Всегда проверяйте достаточно ли у вас RAM для выделенных буферов

Также обратите внимание на значение переменной max_connections.

В предыдущем примере max_connections=2048. Это достаточно много. Проверьте, хватит ли у вас ресурсов на такое количество одновременных соединений.

Встречаются случаи, когда пользователи устанавливали значение max_connections значительно больше, чем их сервера могли обслужить.
Это приводило к непредсказуемым крушениям MySQL сервера при резко возросших нагрузках на обслуживаемые веб-ресурсы.

Устанавливайте правильное значение max_connections

Также MySQL сервер может испытывать нехватку других ресурсов. Обычно информация об ошибке содержится в error log. Анализируйте эту информацию и устраните проблему.
Однако не всегда сам MySQL сервер виноват в нехватке ресурсов. Может так случиться, что их заняло другое приложение. В таком случае используйте системные средства для мониторинга, чтобы выявить виновника.

Используйте средства мониторинга ОС

Мониторинг позволяет выявить приложения, которые потребляют избыточное количество ресурсов, которое приводит к крушению MySQL сервера.

Как мы ранее рассмотрели сообщение Lost connection to MySQL server может также обозначать timeout. Если error log не содержит других ошибок или вы подозреваете именно этот случай, добавьте опцию log_warnings=2 в конфигурационный файл и проверьте error log после получения сообщения.

Используйте опцию log_warnings=2 чтобы отследить имеются ли у вас отклонённые соединения

Иногда ошибка повторяется только при конкурентных запросах. Используйте дополнительное програмное обеспечение и general log, чтобы понять каких именно. Я не буду здесь останавливаться на данной теме подробнее, поскольку она достаточно сложна и требует индивидуального решения.

Источник