Внезапная ошибка "сервер MySQL ушла" на сайте PHP
Сегодня один из моих веб-сайтов начал показывать
Error Number: 2006
MySQL server has gone away
Это клиентский сайт с низким трафиком, работающий под Apache 2.2.9 (Debian), PHP 5.2.6-1 + lenny3 (с использованием Framework CodeIgniter 1.7.1) и MySQL 5.0.51a. Я, очевидно, узнал об ошибке, но все возможные решения подразумевают, что есть большие запросы, которые могут закончиться, и reset соединение, или попадание в пределы пакета. Однако это не так, это небольшая база данных, обработанная простейшими запросами. Чтобы быть уверенным в этом, я составил несколько запросов, чтобы вернуть одну строку, все еще ту же ошибку.
Учетные данные базы данных прекрасны, я даже могу войти непосредственно в mysql, запускать некоторые запросы на сайт и мгновенно получать нужные данные. На одном сервере есть несколько других сайтов и подключение к базе данных, гораздо большие сайты, и у всех их нет проблем.
Я пробовал:
- Перезапуск MySQL
- Перезапуск всего сервера
- Поиск ошибок в журналах (как Apache, так и MySQL, нет)
- Проверка прав пользователя db
- Изменение
mysql.connect_timeout
и default_socket_timeout
в PHP
- Изменение
max_allowed_packet
в MySQL
- Чтение официальных документов, форума и всего в SO, в котором говорится, что "сервер MySQL ушел"
New:
- Отключение постоянных подключений в PHP
- Изменение
wait_timeout
и connect_timeout
в MySQL
Update:
Похоже, что это связано с временем выполнения моего script: он извлекает некоторую информацию с помощью PHP-клиента Facebook, и этот вызов, похоже, случайно не работает сегодня, поэтому у меня нет данных из Facebook или ошибки MySQL. Но, к моему удивлению, ни одно из данных решений, похоже, не связано с таймаутом.
Любые идеи? спасибо за ваше время!
Ответы
Ответ 1
Как я уже сказал в своем обновлении, я пришел к выводу, что проблема с MySQL возникает, когда ссылка на Facebook занимает больше времени, чем максимальное время соединения с БД. Ни одно из предложений не могло превзойти это ограничение, поэтому я решил обойти его и снова подключиться каждый раз, когда предполагаю, что ссылка, возможно, ушла.
Итак, после каждого звонка в Facebook я использовал следующий код:
$this->load->database();
$this->db->reconnect();
Это особое решение при использовании CodeIgniter, и функция AFAIK db- > reconnect() доступна только с версии 1.7.2, поэтому я обновил ее, чтобы работать.
Спасибо всем за ваши ответы!
Ответ 2
Вероятно, это время соединения, влияющее на ваши постоянные соединения в PHP. Я видел их все время. Параметр тайм-аута находится внутри самой MySQL.
Ваши варианты включают:
- не использовать постоянные соединения
- отключение таймаута ожидания на сервере MySQL
- захват ошибки
Я всегда переношу пересоединение в свой собственный класс PDO, поэтому я даже не могу вспомнить, если PHP повторно подключается или нет. В любом случае это легко исправить. По запросу уловить и снова подключиться.
Я сгенерировал эту ошибку в прошлом с помощью InnoDB. Если вы используете этот движок, какой результат SHOW ENGINE INNODB STATUS
после сбоя?
Ответ 3
Поскольку другие сайты работают, мы можем предположить, что это связано с вашим сайтом (а не с сервером). В официальных документах упоминается, что это может произойти, если вы попытаетесь выполнить запросы после закрытия подключения к серверу. Есть ли у вас крючки в CodeIgniter, которые делают что-то в конце запроса, где соединение с базой данных может быть закрыто?
Ответ 4
Вы упомянули, что это задача на ночь, и вы получаете данные FaceBook и т.д. Продолжается ли процесс в течение длительного времени?
У меня был недавний script, который перемещает данные из одного кластера в другой и преобразует форматы и т.д. Этот script работает 24/7, перемещая эти данные. Я обнаружил, что с постоянными соединениями или без них библиотеки MySQL все равно выпадают через несколько минут (иногда 5 минут, а иногда и дольше).
Единственное, что я нашел, чтобы обойти это для моего случая, - это установить проверку времени в моем обертке и проверить, сколько времени прошло с момента последнего подключения к предыдущему запросу перед выполнением запроса. Я установил его, чтобы проверить, было ли это больше 2 минут, и если это так, чтобы восстановить соединение, для установки флажка "new_link" (4-й параметр) в mysql_connect установлено значение false.
Сменив это, у меня никогда не было такой же ошибки.