Ошибки "server has gone away" редко встречаются в обычных php-проектах со стандартными настройками сервера и базы, но зато там, где они могут образоваться, разработчики зачастую не предусматривают большинства подобных ситуаций. В чем же причина таких ошибок?
Эти ошибки относятся к ситуации, когда в процессе отправки запроса, ожидания результата или при его получении обрывается соединение между php и сервером mysql. Это может происходить в следующих распространенных ситуациях:
Вы используете persistent connection к mysql и одновременно с этим произошло что-то из следующего:
Соединение было открыто и длительное время бездействовало. Сервер закрыл соединение по таймауту, а php узнал об этом только когда попытался сделать запрос.
Сервер mysql был перезапущен или соединение со стороны сервера было "убито" вручную. В обоих случаях нужно переоткрыть соединение с mysql.
Вы выполнили fork php-процесса, но пытаетесь пользоваться "старым соединением", полученным от родительского процесса. Соединение с БД нужно просто переоткрыть.
Между сервером с php и сервером mysql упала/"моргнула" сеть или начал работать некорректно настроенный фаервол. Проверить качество соединения можно, если со стороны сервера с php с помощью консольного mysql-клиента соединиться с сервером и сделать любой запрос к базе - если ответ получен, значит, связь между серверами как минимум есть и работает.
Так же часто такая ситуация бывает и при использовании балансировщика запросов между несколькими серверами mysql.
Универсального решения этой ошибки не существует, но для ситуаций простых я дам следующий набор решений:
Не используйте persistent connection на сайтах, на которых нет нагрузки. Будет печально, если единственный за день пришедший пользователь получит 500-ую ошибку вместо сайта из-за того, что соединение висело 8 часов без дела и "умерло" по таймауту.
В ситуациях с fork и при написании демонов на php переоткрывайте соединение при подобной ошибке.
Пример обработки обрыва соединения и переоткрытия для фреймворка Yii 1.1.x
... function query($query, $noretry = false) try { return Yii::app()->db->query($query); } catch (\Exception $e) { if (!$noretry && preg_match('/gone away/',$e->getMessage()) { Yii::app()->db->close(); Yii::app()->db->open(); return $this->query($query, true); } else { throw $e; } } } ...
В большинстве случаев этот код является костылём и его использование хоть и замаскирует видимую часть проблемы, но не решит ее причину. Причины поведения как всегда нужно смотреть в логах mysql и балансировщика, проводить диагностику соединений и читать написанный код. Обычно причина проблемы довольно простая, но выходит за рамки опыта конкретного разработчика или админа.
Протокол WebSocket имеет свои преимущества и свои недостатки: детальный разбор
Не секрет, что хорошо настроенный сервер "падает" гораздо реже, чем доступ из него в Интернет
Позволяет решать интеллектуальные задачи помимо задач самого мониторинга
И снова о маленьких сетевых фокусах ради надежности работы web-сервисов
Особенности серверных приложений, работающих с сетью IoT-устройств на практике и в теории