nodejs mysql Error: conexión perdida El servidor cerró la conexión

89

cuando uso el nodo mysql, aparece un error entre las 12:00 y las 2:00 de que el servidor cierra la conexión TCP. Este es el mensaje completo:

Error: Connection lost: The server closed the connection.
at Protocol.end (/opt/node-v0.10.20-linux-x64/IM/node_modules/mysql/lib/protocol/Protocol.js:73:13)
at Socket.onend (stream.js:79:10)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
at process._tickCallback (node.js:415:13)

Ahí está la solución . Sin embargo, después de intentarlo de esta manera, el problema también aparece. ahora no se como hacer. ¿Alguien resuelve este problema?

Esta es la forma en que escribí, sigue la solución:

    var handleKFDisconnect = function() {
    kfdb.on('error', function(err) {
        if (!err.fatal) {
            return;
        }
        if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
            console.log("PROTOCOL_CONNECTION_LOST");
            throw err;
        }
        log.error("The database is error:" + err.stack);

        kfdb = mysql.createConnection(kf_config);

        console.log("kfid");

        console.log(kfdb);
        handleKFDisconnect();
    });
   };
   handleKFDisconnect();
JackieLin
fuente

Respuestas:

160

Intente usar este código para manejar la desconexión del servidor:

var db_config = {
  host: 'localhost',
    user: 'root',
    password: '',
    database: 'example'
};

var connection;

function handleDisconnect() {
  connection = mysql.createConnection(db_config); // Recreate the connection, since
                                                  // the old one cannot be reused.

  connection.connect(function(err) {              // The server is either down
    if(err) {                                     // or restarting (takes a while sometimes).
      console.log('error when connecting to db:', err);
      setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
    }                                     // to avoid a hot loop, and to allow our node script to
  });                                     // process asynchronous requests in the meantime.
                                          // If you're also serving http, display a 503 error.
  connection.on('error', function(err) {
    console.log('db error', err);
    if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
      handleDisconnect();                         // lost due to either server restart, or a
    } else {                                      // connnection idle timeout (the wait_timeout
      throw err;                                  // server variable configures this)
    }
  });
}

handleDisconnect();

En su código me faltan las partes después connection = mysql.createConnection(db_config);

NubladoMármol
fuente
ok, intentaré esto. pero ¿cómo podría simular esta situación?
jackieLin
1
Solo un consejo: estoy probando la reconexión reiniciando el servicio mysql para asegurarme de que todo funcione bien.
kriskodzi
2
@jackieLin puede simular la situación, reiniciando el servicio mysql, en ubuntu sudo service mysql restart
igor
1
Gracias @ user3073745, este problema se resuelve reiniciando
jackieLin
1
Funciona perfectamente para el nodo 8. *, npm 5.6.0 y mysql: 5.7 ... ¡¡Gracias !!
JRichardsz
47

No recuerdo mi caso de uso original para este mecanismo. Hoy en día, no puedo pensar en ningún caso de uso válido.

Su cliente debería poder detectar cuándo se pierde la conexión y permitirle volver a crearla. Si es importante que parte de la lógica del programa se ejecute utilizando la misma conexión, utilice transacciones.

tl; dr; No utilice este método.


Una solución pragmática es obligar a MySQL a mantener viva la conexión:

setInterval(function () {
    db.query('SELECT 1');
}, 5000);

Prefiero esta solución al grupo de conexiones y al manejo de la desconexión porque no requiere estructurar su código de una manera que sea consciente de la presencia de conexión. Hacer una consulta cada 5 segundos asegura que la conexión permanecerá activa y PROTOCOL_CONNECTION_LOSTno ocurrirá.

Además, este método asegura que mantiene viva la misma conexión , en lugar de volver a conectarla. Esto es importante. Considere lo que sucedería si su script dependiera LAST_INSERT_ID()y la conexión mysql se restablecieran sin que usted se dé cuenta.

Sin embargo, esto solo garantiza que no se produzca el tiempo de espera de conexión ( wait_timeouty interactive_timeout). Fallará, como se esperaba, en todos los demás escenarios. Por lo tanto, asegúrese de manejar otros errores.

Gajus
fuente
1
Solo por curiosidad, ¿dónde pondrías esa consulta de base de datos? En la parte inferior del servidor nodejs, ¿verdad? El único problema es que solo uso mysql para autenticar a un usuario una vez, y luego almaceno sus datos en un objeto de usuario temporal para mi juego de rol. No sé por qué recibí este error de mysql cerrado al azar hoy, hmm. También estoy cerrando la conexión correctamente, etc.
NiCk Newman
1
Debe conectarse a la base de datos y desconectarse a pedido. Esta solución es para servicios que se ejecutan continuamente y utilizan la conexión de la base de datos en todo momento.
Gajus
1
Ninguno de los dos suena probable dado que su código sigue el patrón descrito (algo similar a gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Si esto sucediera solo una o dos veces entre miles de consultas, asumiría problemas de conectividad, sobrecarga del servidor o algo por el estilo.
Gajus
2
¡Esa fue posiblemente la peor sugerencia jamás! Una persona que sugiere que debe martillar la base de datos con consultas sólo para que la conexión no funcione, ¿no? ¿Qué pasa si 100 personas hacen esto? o por qué no 10 000, si su aplicación lo nota, el hilo debe devolverse al grupo de subprocesos de MYSQL ¡NO acaparar un hilo para que su código débil no se rompa! ! ¡Esto es increíble, es una mierda gracias a Dios que FB no te tuvo como arquitecto principal!
Patrik Forsberg
2
He actualizado la respuesta para reflejar que no recomiendo este enfoque. Gracias por el aviso Patrik.
Gajus
3

La mejor solución es usar la piscina; me encargaré de esto por usted.

const pool = mysql.createPool({
  host: 'localhost',
  user: '--',
  database: '---',
  password: '----'
});

// ... later
pool.query('select 1 + 1', (err, rows) => { /* */ });

https://github.com/sidorares/node-mysql2/issues/836

Lalgulab Khatkar
fuente
1

Crear y destruir las conexiones en cada consulta puede ser complicado, tuve algunos dolores de cabeza con la migración de un servidor cuando decidí instalar MariaDB en lugar de MySQL. Por alguna razón en el archivo etc / my.cnf, el parámetro wait_timeout tenía un valor predeterminado de 10 segundos (hace que la persistencia no se pueda implementar). Luego, la solución se configuró en 28800, eso es 8 horas. Bueno, espero ayudar a alguien con esta "güevonada" ... disculpe mi mal inglés.

Torres Aleks
fuente