example - "El servidor MySQL se ha ido" con Ruby on Rails
rails with mysql (11)
Después de que nuestra aplicación Ruby on Rails se haya ejecutado por un tiempo, comienza a arrojar 500s con "El servidor MySQL se ha ido". A menudo esto sucede durante la noche. Ha comenzado a hacer esto recientemente, sin cambios obvios en la configuración de nuestro servidor.
Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets`
Reiniciar los mongrels (no el servidor MySQL) lo corrige.
como podemos arreglar esto?
La conexión al servidor MySQL probablemente se agote.
Debería poder aumentar el tiempo de espera en MySQL, pero para una solución correcta, haga que su código verifique que la conexión de la base de datos aún esté activa y vuelva a conectarse si no es así.
El uso de reconexión: verdadero en la base de datos.yml causará que la conexión de la base de datos se restablezca DESPUÉS de que se produzca el error ActiveRecord :: StatementInvalid (como mencionó Dave Cheney).
Lamentablemente, al agregar un reintento en la operación de la base de datos, pareció necesario evitar el tiempo de espera de la conexión:
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
Algo más que ver es que la configuración de Unicorn es correcta. Consulte el manejo de before_fork y after_fork de la conexión de ActiveRecord aquí: https://gist.github.com/nebiros/2776085#file-unicorn-rb
¿Monitoreas la cantidad de conexiones o hilos MySQL abiertos? ¿Cuál es la configuración de mysql.ini para max_connections?
mysql> show status;
Observe Conexiones, Max_used_connections, Threads_connected y Threads_created.
Es posible que necesite aumentar los límites en su configuración de MySQL, o quizás los rieles no cierren la conexión correctamente *.
Nota: solo he usado Ruby on Rails brevemente ...
La documentación de MySQL para el estado del servidor está en http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html .
Como han dicho otros colaboradores de este hilo, lo más probable es que el servidor MySQL haya cerrado la conexión a su aplicación Ruby on Rails debido a la inactividad. El tiempo de espera predeterminado es 28800 segundos u 8 horas.
set-variable = wait_timeout=86400
Agregar esta línea a su /etc/my.cnf
elevará el tiempo de espera a 24 horas http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#option_mysqld_wait_timeout .
Aunque la documentación no lo indica, un valor de 0 puede inhabilitar por completo el tiempo de espera, pero tendría que experimentar ya que esto es solo una especulación.
Sin embargo, hay otras tres situaciones que conozco que pueden generar ese error. El primero es el servidor MySQL que se reinicia. Obviamente, esto soltará todas las conexiones, pero como el cliente MySQL es pasivo, no se notará hasta que realices la siguiente consulta.
La segunda condición es si alguien elimina su consulta de la línea de comando de MySQL, y esto también deja de estar conectada, ya que podría dejar al cliente en un estado indefinido.
El último es si su servidor MySQL se reinicia debido a un error interno fatal. Es decir, si está haciendo una simple consulta en una tabla y ve instantáneamente ''MySQL se ha ido'', examinaría de cerca los registros de su servidor para verificar si hay errores de hardware o corrupción de la base de datos.
Esto probablemente se deba a que las conexiones persistentes con MySQL se van (el tiempo de espera es probable si está sucediendo durante la noche) y Ruby on Rails no está restableciendo la conexión, lo que debería estar haciendo por defecto:
En el proveedor de archivos / rails / actionpack / lib / action_controller / dispatcher.rb está el código:
if defined?(ActiveRecord)
before_dispatch { ActiveRecord::Base.verify_active_connections! }
to_prepare(:activerecord_instantiate_observers) {ActiveRecord::Base.instantiate_observers }
end
El método verify_active_connections!
realiza varias acciones, una de las cuales es recrear cualquier conexión vencida.
La causa más probable de este error es que esto se debe a que un parche mono ha redefinido al despachador para que no llame a verify_active_connections!
¡o verify_active_connections!
ha sido cambiado, etc.
Primero, determine max_connections en MySQL:
show variables like "max_connections";
Debe asegurarse de que la cantidad de conexiones que está realizando en su aplicación Ruby on Rails sea menor que la cantidad máxima permitida de conexiones. Tenga en cuenta que las conexiones adicionales pueden provenir de sus trabajos cron , procesos de retraso de trabajo (cada uno tendría el mismo tamaño de grupo en su database.yml
datos.yml), etc.
Supervise las conexiones SQL a medida que avanza en su aplicación, ejecute procesos, etc. haciendo lo siguiente en MySQL:
show status where variable_name = ''Threads_connected'';
Es posible que desee considerar el cierre de las conexiones después de que un Thread
finalice la ejecución, ya que las conexiones de la base de datos no se cierran automáticamente (creo que esto es un problema menor con Reaper, aplicaciones de Ruby on Rails):
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
Prueba ActiveRecord::Base.connection.verify!
en Ruby on Rails 4. Verifique que el servidor se conecte y vuelva a conectar si no está conectado.
Ruby on Rails 2.3 tiene una opción de reconexión para su conexión a la base de datos:
production:
# Your settings
reconnect: true
Ver:
¡Buena suerte!
Tuve este problema al enviar declaraciones realmente grandes a MySQL. MySQL limita el tamaño de las declaraciones y cerrará la conexión si supera el límite.
set global max_allowed_packet = 1048576; # 2^20 bytes (1 MB) was enough in my case
Tuve este problema en una aplicación de Ruby on Rails 3, usando la gema mysql2
. Copié la consulta ofensiva e intenté ejecutarla en MySQL directamente, y obtuve el mismo error, "El servidor MySQL se ha ido".
La consulta en cuestión fue muy, muy grande. Un inserto muy grande (+1 MB). El campo en el que traté de insertar era una columna TEXTO y su tamaño máximo es 64 KB. En lugar de lanzar un error, la conexión desapareció.
Aumenté el tamaño del campo y obtuve lo mismo, así que todavía no estoy seguro de cuál fue el problema exacto. El punto es que estaba en la base de datos debido a alguna consulta extraña. ¡De todas formas!