"Сервер MySQL ушел" с Ruby on Rails
После того, как наше приложение Ruby on Rails запустилось некоторое время, он начинает бросать 500 с "сервер MySQL ушел". Часто это происходит за одну ночь. Он начал делать это недавно, без каких-либо очевидных изменений в конфигурации сервера.
Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets`
Перезапуск mongrels (а не сервер MySQL) исправляет его.
Как мы можем это исправить?
Ответы
Ответ 1
Вероятно, это связано с постоянным подключением к MySQL (время ожидания, скорее всего, происходит в течение ночи), а Ruby on Rails не восстанавливает соединение, которое должно выполняться по умолчанию:
В файле vendor/rails/actionpack/lib/action_controller/dispatcher.rb указан код:
if defined?(ActiveRecord)
before_dispatch { ActiveRecord::Base.verify_active_connections! }
to_prepare(:activerecord_instantiate_observers) {ActiveRecord::Base.instantiate_observers }
end
Метод verify_active_connections!
выполняет несколько действий, одним из которых является воссоздание любых истекших соединений.
Наиболее вероятной причиной этой ошибки является то, что это связано с тем, что патч обезьяны переопределил диспетчера, чтобы он не вызывал verify_active_connections!
, или verify_active_connections!
, и т.д.
Ответ 2
Ruby on Rails 2.3 имеет параметр повторного подключения для подключения к базе данных:
production:
# Your settings
reconnect: true
См:
Удачи!
Ответ 3
Как говорили другие участники этой темы, скорее всего, сервер MySQL закрыл соединение с вашим приложением Ruby on Rails из-за неактивности. Таймаут по умолчанию - 28800 секунд или 8 часов.
set-variable = wait_timeout=86400
Добавление этой строки в ваш /etc/my.cnf
приведет к увеличению тайм-аута до 24 часов
http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#option_mysqld_wait_timeout.
Хотя документация не указывает на это, значение 0 может полностью отключить таймаут, но вам нужно будет поэкспериментировать, поскольку это всего лишь предположение.
Есть, однако, три других ситуации, о которых я знаю, которые могут генерировать эту ошибку. Во-первых, перезагружается сервер MySQL. Это, очевидно, приведет к удалению всех подключений, но поскольку клиент MySQL является пассивным, и это не будет замечено, пока вы не выполните следующий запрос.
Вторым условием является то, что кто-то убивает ваш запрос из командной строки MySQL, и это также отключает соединение, поскольку оно может оставить клиента в состоянии undefined.
Последнее, если ваш сервер MySQL перезапустится из-за фатальной внутренней ошибки. То есть, если вы делаете простой запрос к таблице и сразу видите, что "MySQL ушел", я бы внимательно рассмотрел журналы вашего сервера, чтобы проверить аппаратную ошибку или повреждение базы данных.
Ответ 4
Сначала определите max_connections в MySQL:
show variables like "max_connections";
Вам нужно убедиться, что количество подключений, которые вы делаете в приложении Ruby on Rails, меньше максимально допустимого количества подключений. Обратите внимание, что дополнительные подключения могут возникать из ваших cron заданий, процессов delayed_job (каждый из них имеет одинаковый размер пула в вашем database.yml
), и др.
Отслеживать соединения SQL при прохождении через приложение, запускать процессы и т.д., выполняя следующие действия в MySQL:
show status where variable_name = 'Threads_connected';
Возможно, вы захотите рассмотреть вопрос о закрытии соединений после завершения выполнения Thread
, поскольку соединения с базой данных не закрываются автоматически (я думаю, что это не проблема с приложениями Ruby on Rails 4 Жнец):
Thread.new do
begin
# Thread work here
ensure
begin
if (ActiveRecord::Base.connection && ActiveRecord::Base.connection.active?)
ActiveRecord::Base.connection.close
end
rescue
end
end
end
Ответ 5
У меня возникла эта проблема при отправке действительно больших операторов в MySQL. MySQL ограничивает размер операторов и закрывает соединение, если вы переходите через предел.
set global max_allowed_packet = 1048576; # 2^20 bytes (1 MB) was enough in my case
Ответ 6
Соединение с сервером MySQL, вероятно, отключается.
Вы должны иметь возможность увеличить время ожидания в MySQL, но для правильного исправления попросите свой код проверить, что соединение с базой данных все еще жив, и повторно подключиться, если это не так.
Ответ 7
Вы отслеживаете количество открытых подключений или потоков MySQL? Каковы ваши настройки mysql.ini для max_connections?
mysql> show status;
Посмотрите на соединения, Max_used_connections, Threads_connected и Threads_created.
Вам может потребоваться увеличить лимиты в вашей конфигурации MySQL, или, возможно, рельсы не закрывают соединение правильно.
Примечание. Я использовал Ruby on Rails ненадолго...
Документация MySQL для статуса сервера находится в http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html.
Ответ 8
Использование reconnect: true в database.yml приведет к восстановлению соединения с базой данных ПОСЛЕ ВЫПОЛНЕНИЯ ошибки ActiveRecord:: StatementInvalid (как упоминал Дэйв Чейни).
К сожалению, добавление повторной попытки в операции с базой данных было необходимо для защиты от таймаута соединения:
begin
do_some_active_record_operation
rescue ActiveRecord::StatementInvalid => e
Rails.logger.debug("Got statement invalid #{e.message} ... trying again")
# Second attempt, now that db connection is re-established
do_some_active_record_operation
end
Ответ 9
Попробуйте ActiveRecord::Base.connection.verify!
в Ruby on Rails 4. Проверьте, проверяет ли сервер и повторно подключается, если он не подключен.
Ответ 10
У меня была эта проблема в приложении Ruby on Rails 3, используя камень mysql2
. Я скопировал нарушающий запрос и попытался запустить его непосредственно в MySQL, и я получил ту же ошибку: "Сервер MySQL ушел".
Вопрос был очень-очень большой. Очень большая вставка (+ 1 MB). В поле, которое я пытался вставить, был столбец TEXT, а их максимальный размер - 64 КБ. Вместо того, чтобы бросать ошибку, соединение ушло.
Я увеличил размер поля и получил то же самое, поэтому я все еще не уверен, что такое точная проблема. Дело в том, что это было в базе данных из-за какого-то странного запроса. В любом случае!
Ответ 11
Что-то еще, чтобы проверить конфигурацию Unicorn правильно. Ниже приведена ссылка before_fork и after_fork на соединение ActiveRecord: https://gist.github.com/nebiros/2776085#file-unicorn-rb