Erro nodejs mysql: Conexão perdida O servidor fechou a conexão

93

quando eu uso o node mysql, aparece um erro entre 12h00 e 2h00 que a conexão TCP foi desligada pelo servidor. Esta é a mensagem completa:

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)

Essa é a solução . Porém, depois de tentar dessa forma, o problema também apareceu. agora não sei como fazer. Alguém conhece esse problema?

Aqui está o jeito que escrevi seguir a solução:

    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
fonte
Note-se que em seu código que você tinha uma mensagem incorreta: if (err.code !== 'PROTOCOL_CONNECTION_LOST') { console.log("PROTOCOL_CONNECTION_LOST"); throw err; }. Você executar o if()bloco se for não PROTOCOL_CONNECTION_LOST e ainda a mensagem diz que é esse erro ... provavelmente muito confuso.
Alexis Wilke

Respostas:

164

Tente usar este código para lidar com a desconexão do 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();

No seu código estou faltando as partes depois connection = mysql.createConnection(db_config);

CloudyMarble
fonte
ok, vou tentar isso. mas como eu poderia simular esta siutation
jackieLin
1
Só uma dica: estou testando a reconexão reiniciando o serviço mysql para garantir que tudo funcione bem.
Kriskodzi 01 de
2
@jackieLin você pode simular a situação, reiniciando o serviço mysql, no serviço ubuntu sudo mysql restart
igor
1
Obrigado @ user3073745, este problema é resolvido reiniciando
jackieLin
1
Funciona perfeitamente para o nó 8. *, npm 5.6.0 e mysql: 5.7 ... Obrigado !!
JRichardsz
47

Não me lembro de meu caso de uso original para esse mecanismo. Hoje em dia, não consigo pensar em nenhum caso de uso válido.

Seu cliente deve ser capaz de detectar quando a conexão é perdida e permitir que você recrie a conexão. Se for importante que parte da lógica do programa seja executada usando a mesma conexão, use as transações.

tl; dr; Não use este método.


Uma solução pragmática é forçar o MySQL a manter a conexão ativa:

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

Eu prefiro esta solução para pool de conexão e tratamento de desconexão porque não requer estruturar seu código de uma forma que esteja ciente da presença de conexão. Fazer uma consulta a cada 5 segundos garante que a conexão permanecerá ativa e PROTOCOL_CONNECTION_LOSTnão ocorrerá.

Além disso, esse método garante que você mantenha a mesma conexão ativa , em vez de reconectar. Isso é importante. Considere o que aconteceria se seu script dependesse de LAST_INSERT_ID()e a conexão do mysql fosse redefinida sem você saber disso?

No entanto, isso apenas garante que o tempo limite de conexão ( wait_timeoute interactive_timeout) não ocorra. Ele falhará, como esperado, em todos os outros cenários. Portanto, certifique-se de lidar com outros erros.

Gajus
fonte
1
Só por curiosidade, onde você colocaria essa consulta de banco de dados? Na parte inferior do servidor nodejs certo? O único problema é que eu só uso o mysql para autenticar um usuário uma vez e, em seguida, armazeno seus dados em um objeto de usuários temporário para o meu jogo rpg. Não sei por que recebi esse erro de mysql fechado aleatoriamente hoje, hmm. Estou fechando a conexão corretamente, etc. também.
NiCk Newman
1
Você deve se conectar ao banco de dados e desconectar sob demanda. Esta solução é para serviços que funcionam continuamente e utilizam conexão de banco de dados o tempo todo.
Gajus
1
Nenhum dos dois parece provável, já que seu código segue o padrão descrito (algo semelhante a gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Se isso acontecesse apenas uma ou duas vezes em milhares de consultas, presumiria problemas de conectividade, sobrecarga do servidor ou algo parecido.
Gajus
3
Essa foi possivelmente a pior sugestão de todos! Uma pessoa sugerindo que você deve martelar o banco de dados com consultas apenas para que a conexão não saia? O que acontecerá se 100 pessoas fizerem isso? ou por que não 10.000, se o seu aplicativo não notar, a thread deve ser retornada ao pool de threads do MYSQL NÃO monopolizando uma thread para que seu código fraco não quebre !, neste caso você implementa a funcionalidade para reconectar se tal evento tiver ocorrido ! Isso é inacreditável, é tão estu *** graças a Deus que o FB não teve você como arquiteto principal !!
Patrik Forsberg
2
Atualizei a resposta para refletir que não recomendo essa abordagem. Obrigado pelo aviso, Patrik.
Gajus de
4

a melhor solução é usar piscina - cuidarei disso para você.

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
fonte
Esta deve ser a resposta aceita. O uso do mecanismo de pool irá ocultar todos os detalhes complicados sobre como lidar com tempos limite de conexão. Além disso, há documentação sobre como usá-lo no node_modules/mysql/Readme.mdarquivo que vem com o módulo de nó MySQL.
Alexis Wilke
1

Criar e destruir as conexões em cada consulta pode ser complicado, tive algumas dores de cabeça com a migração do servidor quando decidi instalar o MariaDB em vez do MySQL. Por alguma razão no arquivo etc / my.cnf o parâmetro wait_timeout tinha um valor padrão de 10 seg (isso faz com que a persistência não possa ser implementada). Então, a solução foi acertada em 28800, são 8 horas. Bem, espero ajudar alguém com essa "güevonada" ... desculpe-me pelo meu péssimo inglês.

Aleks Towers
fonte