nodejs mysql Fehler: Verbindung unterbrochen Der Server hat die Verbindung geschlossen

86

Wenn ich den Knoten MySQL verwende, wird zwischen 12:00 und 2:00 Uhr ein Fehler angezeigt, dass die TCP-Verbindung vom Server heruntergefahren wird. Dies ist die vollständige Nachricht:

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)

Da ist die Lösung . Nachdem ich es auf diese Weise versucht habe, tritt jedoch auch das Problem auf. jetzt weiß ich nicht wie ich es machen soll. Trifft jemand dieses Problem?

So habe ich geschrieben, folge der Lösung:

    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
quelle

Antworten:

155

Versuchen Sie, diesen Code zu verwenden, um die Server-Trennung zu behandeln:

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

In Ihrem Code fehlen mir die Teile danach connection = mysql.createConnection(db_config);

CloudyMarble
quelle
ok, ich werde es versuchen. aber wie könnte ich diese siutation simulieren
jackieLin
1
Nur ein Tipp: Ich teste die Wiederverbindung, indem ich den MySQL-Dienst neu starte, um sicherzustellen, dass alles gut funktioniert.
Kriskodzi
2
@jackieLin Sie können die Situation simulieren, MySQL-Dienst neu starten, auf Ubuntu Sudo-Dienst MySQL-Neustart
igor
1
Vielen Dank @ user3073745, dieses Problem wird durch Neustart gelöst
jackieLin
1
Funktioniert perfekt für Knoten 8. *, npm 5.6.0 und MySQL: 5.7 ... Danke !!
JRichardsz
46

Ich erinnere mich nicht an meinen ursprünglichen Anwendungsfall für diesen Mechanismus. Heutzutage kann ich mir keinen gültigen Anwendungsfall vorstellen.

Ihr Client sollte erkennen können, wann die Verbindung unterbrochen wurde, und es Ihnen ermöglichen, die Verbindung neu zu erstellen. Wenn es wichtig ist, dass ein Teil der Programmlogik über dieselbe Verbindung ausgeführt wird, verwenden Sie Transaktionen.

tl; dr; Verwenden Sie diese Methode nicht.


Eine pragmatische Lösung besteht darin, MySQL zu zwingen, die Verbindung aufrechtzuerhalten:

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

Ich bevorzuge diese Lösung gegenüber dem Verbindungspool und der Behandlung von Verbindungsabbrüchen, da Ihr Code nicht so strukturiert werden muss, dass die Anwesenheit der Verbindung berücksichtigt wird. Wenn Sie alle 5 Sekunden eine Abfrage durchführen, wird sichergestellt, dass die Verbindung weiterhin besteht und PROTOCOL_CONNECTION_LOSTnicht hergestellt wird.

Darüber hinaus stellt diese Methode sicher, dass Sie dieselbe Verbindung aufrecht erhalten , anstatt erneut eine Verbindung herzustellen. Das ist wichtig. Überlegen Sie, was passieren würde, wenn Ihr Skript verwendet LAST_INSERT_ID()und die MySQL-Verbindung zurückgesetzt würde, ohne dass Sie sich dessen bewusst wären?

Dies stellt jedoch nur sicher, dass kein Verbindungszeitlimit ( wait_timeoutund interactive_timeout) auftritt. In allen anderen Szenarien schlägt dies erwartungsgemäß fehl. Stellen Sie daher sicher, dass Sie andere Fehler behandeln.

Gajus
quelle
1
Nur neugierig, wo würden Sie diese Datenbankabfrage platzieren? Am unteren Rand des NodeJS-Servers, oder? Das einzige Problem ist, dass ich einen Benutzer nur einmal mit MySQL authentifiziere und dann seine Daten in einem temporären Benutzerobjekt für mein RPG-Spiel speichere. Ich weiß nicht, warum ich diesen zufälligen MySQL-Fehler heute zufällig bekommen habe, hmm. Ich schließe die Verbindung auch richtig usw.
NiCk Newman
1
Sie sollten eine Verbindung zur Datenbank herstellen und die Verbindung nach Bedarf trennen. Diese Lösung ist für Dienste gedacht, die kontinuierlich ausgeführt werden und jederzeit eine Datenbankverbindung verwenden.
Gajus
1
Beides klingt nicht wahrscheinlich, da Ihr Code dem beschriebenen Muster folgt (ähnlich wie gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Wenn dies nur ein- oder zweimal bei Tausenden von Abfragen passiert wäre, würde ich Konnektivitätsprobleme, Serverüberlastung oder ähnliches annehmen.
Gajus
2
Das war wahrscheinlich der schlimmste Vorschlag aller Zeiten! Eine Person, die vorschlägt, dass Sie die Datenbank mit Abfragen hämmern sollten, damit die Verbindung nicht unterbrochen wird? Was passiert, wenn 100 Personen dies tun? oder warum nicht 10 000. Wenn Ihre App dies nicht bemerkt, sollte der Thread an den MYSQL-Thread-Pool zurückgegeben werden, ohne einen Thread zu blockieren, damit Ihr schwacher Code nicht kaputt geht! In diesem Fall implementieren Sie Funktionen zum erneuten Verbinden, wenn ein solches Ereignis aufgetreten ist ! Das ist unglaublich, Gott sei Dank, dass FB dich nicht als Hauptarchitekten hatte !!
Patrik Forsberg
2
Ich habe die Antwort aktualisiert, um zu berücksichtigen, dass ich diesen Ansatz nicht empfehle. Vielen Dank für das Heads-up Patrik.
Gajus
3

Eine bessere Lösung ist die Verwendung eines Pools.

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
quelle
1

Das Erstellen und Zerstören der Verbindungen in jeder Abfrage ist möglicherweise kompliziert. Ich hatte einige Probleme mit einer Servermigration, als ich mich entschied, MariaDB anstelle von MySQL zu installieren. Aus irgendeinem Grund hatte der Parameter wait_timeout in der Datei etc / my.cnf einen Standardwert von 10 Sekunden (dies führt dazu, dass die Persistenz nicht implementiert werden kann). Dann wurde die Lösung auf 28800 eingestellt, das sind 8 Stunden. Nun, ich hoffe, ich helfe jemandem mit dieser "güevonada" ... entschuldige mich für mein schlechtes Englisch.

Aleks Towers
quelle