nodejs mysql Errore: connessione persa Il server ha chiuso la connessione


93

quando utilizzo il nodo mysql, tra le 12:00 e le 2:00 viene visualizzato un errore che indica che la connessione TCP viene interrotta dal server. Questo è il messaggio 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)

C'è la soluzione . Tuttavia, dopo aver provato in questo modo, appare anche il problema. ora non so come fare. Qualcuno incontra questo problema?

Ecco il modo in cui ho scritto per seguire la soluzione:

    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();

Si noti che nel codice si ha un messaggio non corretto: if (err.code !== 'PROTOCOL_CONNECTION_LOST') { console.log("PROTOCOL_CONNECTION_LOST"); throw err; }. Si esegue il if()blocco se è non è PROTOCOL_CONNECTION_LOST , eppure il messaggio dice che è che l'errore ... probabilmente molto confuso.
Alexis Wilke

Risposte:


164

Prova a utilizzare questo codice per gestire la disconnessione del server:

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();

Nel tuo codice mi mancano le parti dopo connection = mysql.createConnection(db_config);


ok, proverò questo. ma come potrei simulare questa situazione
jackieLin

1
Solo un suggerimento: sto testando la riconnessione riavviando il servizio mysql per assicurarmi che tutto funzioni bene.
kriskodzi

2
@jackieLin puoi simulare la situazione, riavviando il servizio mysql, su ubuntu sudo service mysql restart
igor

1
Grazie @ user3073745, questo problema è risolto dal riavvio
jackieLin

1
Funziona perfettamente per il nodo 8. *, npm 5.6.0 e mysql: 5.7 ... Grazie !!
JRichardsz

47

Non ricordo il mio caso d'uso originale per questo meccanismo. Al giorno d'oggi, non riesco a pensare a nessun caso d'uso valido.

Il tuo client dovrebbe essere in grado di rilevare quando la connessione è persa e consentirti di ricreare la connessione. Se è importante che parte della logica del programma venga eseguita utilizzando la stessa connessione, utilizzare le transazioni.

tl; dr; Non utilizzare questo metodo.


Una soluzione pragmatica consiste nel forzare MySQL a mantenere attiva la connessione:

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

Preferisco questa soluzione al pool di connessioni e alla gestione della disconnessione perché non richiede di strutturare il codice in modo che sia consapevole della presenza della connessione. L'esecuzione di una query ogni 5 secondi garantisce che la connessione rimanga attiva e PROTOCOL_CONNECTION_LOSTnon si verifichi.

Inoltre, questo metodo ti assicura di mantenere viva la stessa connessione , invece di riconnetterti. Questo è importante. Considera cosa succederebbe se il tuo script si basasse su LAST_INSERT_ID()e la connessione mysql fosse stata ripristinata senza che tu ne fossi consapevole?

Tuttavia, ciò garantisce solo che il timeout di connessione ( wait_timeoute interactive_timeout) non si verifichi. Come previsto, fallirà in tutti gli altri scenari. Pertanto, assicurati di gestire altri errori.


1
Sono solo curioso, dove metteresti quella query db? Nella parte inferiore del server nodejs, giusto? L'unico problema è che utilizzo mysql solo una volta per autenticare un utente, quindi memorizzo i suoi dati in un oggetto utente temporaneo per il mio gioco rpg. Non so perché ho ricevuto questo errore di chiusura di mysql in modo casuale oggi, hmm. Sto chiudendo correttamente anche la connessione, ecc.
NiCk Newman

1
È necessario connettersi al database e disconnettersi su richiesta. Questa soluzione è per servizi che vengono eseguiti continuamente e utilizzano la connessione al database in ogni momento.
Gajus

1
Nessuno dei due sembra probabile dato che il tuo codice segue lo schema descritto (qualcosa di simile a gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Se ciò accadesse solo una o due volte su migliaia di query, presumerei problemi di connettività, sovraccarico del server o qualcosa del genere.
Gajus

3
Questo è stato forse il peggior suggerimento in assoluto! Una persona che suggerisce di martellare il database con le query solo in modo che la connessione non funzioni, no? Cosa succede se 100 persone lo fanno? o perché no 10.000, se la tua app nota, il thread dovrebbe essere restituito al pool di thread MYSQL NON monopolizzare un thread in modo che il tuo codice debole non si rompa !, in questo caso implementerai la funzionalità per la riconnessione se tale evento si è verificato ! È incredibile, è una tale cosa, grazie a Dio che FB non ti ha avuto come capo architetto !!
Patrik Forsberg

2
Ho aggiornato la risposta per riflettere che non consiglio questo approccio. Grazie per l'avviso Patrik.
Gajus


4

la soluzione migliore è usare la piscina - gestirla male per te.

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


Questa dovrebbe essere la risposta accettata. L'uso del meccanismo del pool nasconderà tutti i dettagli complicati su come gestire i timeout di connessione. Inoltre, c'è la documentazione su come usarlo nel node_modules/mysql/Readme.mdfile fornito con il modulo del nodo MySQL.
Alexis Wilke

1

Creare e distruggere le connessioni in ogni query potrebbe essere complicato, ho avuto qualche grattacapo con una migrazione del server quando ho deciso di installare MariaDB invece di MySQL. Per qualche motivo nel file etc / my.cnf il parametro wait_timeout aveva un valore predefinito di 10 sec (fa sì che la persistenza non possa essere implementata). Quindi, la soluzione è stata impostata su 28800, ovvero 8 ore. Beh, spero di aiutare qualcuno con questa "güevonada" ... scusatemi per il mio cattivo inglese.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.