nodejs mysql Erreur: connexion perdue Le serveur a fermé la connexion

89

lorsque j'utilise le nœud mysql, une erreur apparaît entre 12h00 et 2h00 indiquant que la connexion TCP est arrêtée par le serveur. Voici le message complet:

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)

Voilà la solution . Cependant, après avoir essayé de cette manière, le problème apparaît également. maintenant je ne sais pas comment faire. Quelqu'un rencontre-t-il ce problème?

Voici comment j'ai écrit suivre la solution:

    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
la source

Réponses:

160

Essayez d'utiliser ce code pour gérer la déconnexion du serveur:

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

Dans votre code, il me manque les pièces après connection = mysql.createConnection(db_config);

NuageuxMarbre
la source
ok, je vais essayer ça. mais comment pourrais-je simuler cette siutation
jackieLin
1
Juste un conseil: je teste la reconnexion en redémarrant le service mysql pour m'assurer que tout fonctionne bien.
kriskodzi le
2
@jackieLin vous pouvez simuler la situation, redémarrer le service mysql, sur ubuntu sudo service mysql restart
igor
1
Merci @ user3073745, ce problème est résolu par redémarrage
jackieLin
1
Fonctionne parfaitement pour le nœud 8. *, npm 5.6.0 et mysql: 5.7 ... Merci !!
JRichardsz
47

Je ne me souviens pas de mon cas d'utilisation d'origine pour ce mécanisme. De nos jours, je ne peux penser à aucun cas d'utilisation valable.

Votre client devrait être en mesure de détecter la perte de la connexion et de vous permettre de recréer la connexion. S'il est important qu'une partie de la logique du programme soit exécutée à l'aide de la même connexion, utilisez des transactions.

tl; dr; N'utilisez pas cette méthode.


Une solution pragmatique consiste à forcer MySQL à maintenir la connexion active:

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

Je préfère cette solution au pool de connexions et à la gestion de la déconnexion car elle ne nécessite pas de structurer votre code de manière à tenir compte de la présence de la connexion. Faire une requête toutes les 5 secondes garantit que la connexion restera active et PROTOCOL_CONNECTION_LOSTne se produira pas.

En outre, cette méthode garantit que vous gardez la même connexion active , par opposition à la reconnexion. C'est important. Considérez ce qui se passerait si votre script s'appuyait LAST_INSERT_ID()et que la connexion mysql avait été réinitialisée sans que vous en soyez conscient?

Cependant, cela garantit uniquement que le délai de connexion ( wait_timeoutet interactive_timeout) ne se produit pas. Il échouera, comme prévu, dans tous les autres scénarios. Par conséquent, assurez-vous de gérer les autres erreurs.

Gajus
la source
1
Juste curieux, où placeriez-vous cette requête de base de données? Au bas du serveur nodejs, non? Le seul problème est que je n'utilise mysql qu'une seule fois pour authentifier un utilisateur, puis je stocke ses données dans un objet utilisateur temporaire pour mon jeu rpg. Je ne sais pas pourquoi j'ai obtenu cette erreur mysql fermée au hasard aujourd'hui, hmm. Je ferme la connexion correctement, etc. aussi.
NiCk Newman
1
Vous devez vous connecter à la base de données et vous déconnecter à la demande. Cette solution est destinée aux services qui s'exécutent en continu et utilisent la connexion à la base de données à tout moment.
Gajus
1
Aucun des deux semble probable étant donné que votre code suit le modèle décrit (quelque chose de similaire à gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Si cela ne se produisait qu'une ou deux fois sur des milliers de requêtes, je supposerais des problèmes de connectivité, une surcharge du serveur ou quelque chose du genre.
Gajus
2
C'était peut-être la pire suggestion jamais faite! Une personne suggérant que vous devriez marteler la base de données avec des requêtes juste pour que la connexion ne se passe pas? Que se passe-t-il si 100 personnes font cela? ou pourquoi pas 10 000, si votre application ne le note pas, le thread doit être renvoyé dans le pool de threads MYSQL PAS monopolisant un thread afin que votre code faible ne se casse pas! ! C´est incroyable, c´est un tel stu *** dieu merci que FB ne vous ait pas eu comme architecte principal !!
Patrik Forsberg
2
J'ai mis à jour la réponse pour refléter que je ne recommande pas cette approche. Merci pour la tête Patrik.
Gajus
3

la meilleure solution est d'utiliser la piscine - mal gérer cela pour vous.

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
la source
1

Créer et détruire les connexions dans chaque requête peut être compliqué, j'ai eu des maux de tête avec une migration de serveur lorsque j'ai décidé d'installer MariaDB à la place de MySQL. Pour une raison quelconque, dans le fichier etc / my.cnf, le paramètre wait_timeout avait une valeur par défaut de 10 s (cela fait que la persistance ne peut pas être implémentée). Ensuite, la solution a été mise en 28800, soit 8 heures. Eh bien, j'espère aider quelqu'un avec cette "güevonada" ... excusez-moi pour mon mauvais anglais.

Tours Aleks
la source