2008-09-19 22 views
38

Después de que nuestra aplicación Ruby on Rails haya funcionado 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."El servidor MySQL se ha ido" con Ruby on Rails

Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets` 

Reinicio de los mestizos (no el servidor MySQL) lo arregla.

¿Cómo podemos solucionar esto?

Respuesta

22

Esto es probablemente causado por las conexiones persistentes con MySQL se va a desaparecer (tiempo de espera es probable si está sucediendo durante la noche) y Ruby on Rails está fallando para restaurar la conexión, que se debe hacer de forma predeterminada:

en el proveedor de archivos/rieles/actionpack/lib/action_controller/dispatcher.rb es 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 la de recrear cualquier conexión expirado.

La causa más probable de este error es que esto se debe a una monkey patch ha redefinido el despachador para no llamar verify_active_connections!, o verify_active_connections! ha sido cambiado, etc.

+2

Sí; Pasé el problema al capturar 'ActiveRecord :: StatementInvalid' una vez y al llamar manualmente' ActiveRecord :: Base.verify_active_connections! 'Cuando me encontré con esto. – conny

+0

@Conny, ¿a dónde va 'ActiveRecord :: StatementInvalid'? en 'application_controller.rb'? ¿O en otro lugar? –

+1

@ChristianFazzini, esto fue dentro de un daemon independiente que cumplía un propósito específico de la aplicación: nunca tuve este problema dentro de una simple aplicación web de Rails. Si tuviera, ahora estaría usando Rails 2.3 o posterior y usaré la opción de reconexión [según lo propuesto por mixonic] (http://stackoverflow.com/a/1175186/23023) – conny

1

Es probable que la conexión con el servidor MySQL se haya agotado.

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 reconectela si no es así.

1

¿Controla la cantidad de conexiones abiertas de MySQL o subprocesos? ¿Cuál es la configuración de mysql.ini para max_connections?

mysql> show status; 

Examine las conexiones, Max_used_connections, Threads_connected y Threads_created.

Es posible que deba aumentar los límites en su configuración de MySQL, o quizás los rieles no cierren la conexión correctamente *.

Nota: Sólo he utilizado Ruby on Rails brevemente ...

La documentación de MySQL para el estado del servidor se encuentra en http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html.

4

Como los otros contribuyentes a este hilo han dicho, 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 

La adición de esta línea a su /etc/my.cnf aumentará el tiempo de espera de 24 horas http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#option_mysqld_wait_timeout.

Aunque la documentación no indica que, un valor de 0 puede desactivar por completo el tiempo de espera, pero que tendría que experimentar ya que esto es sólo 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 comandos 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.

+0

En las aplicaciones de rails en las que he trabajado tengo no visto El registro activo se vuelve a conectar durante la solicitud actual, pero se vuelve a conectar en la siguiente solicitud, por lo tanto, esta puede ser una condición temporal si puede copiar una excepción por mestizo. –

1

Uso de la reconexión: true en la base de datos.yml hará 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).

añadiendo Desafortunadamente un reintento de la operación de la base de datos parecía necesario para prevenir un 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 
0

he tenido este problema en un rubí en los carriles 3 aplicación, utilizando 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 intentaba 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 aún 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!

+0

Ver mi respuesta - Sospecho que tuvo el mismo problema que yo –

2

primer lugar, determinar las max_connections en MySQL:

show variables like "max_connections"; 

Usted necesita asegurarse de que el número de conexiones que está haciendo en su aplicación Ruby on Rails es menor que el número máximo permitido de conexiones. Tenga en cuenta que las conexiones adicionales pueden ser procedentes de sus cron puestos de trabajo, procesos delayed_job (cada uno tendrían el mismo tamaño de la piscina en su database.yml), etc.

Monitorear las conexiones SQL a medida que avanza a través de su aplicación, los procesos se ejecutan, etc.haciendo lo siguiente en MySQL:

show status where variable_name = 'Threads_connected'; 

Es posible que desee considerar el cierre de conexiones después de una ejecución Thread acabados como las conexiones de base de datos no se cierran automáticamente (creo que esto es un problema menor con Ruby on Rails 4 aplicaciones Reaper):

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 
1

Trate ActiveRecord::Base.connection.verify! en Ruby on Rails 4. Verificar ping al servidor y vuelve a conectar si no está conectado.

2

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 
Cuestiones relacionadas