nodejs mysqlエラー:接続が失われましたサーバーが接続を閉じました


89

ノードmysqlを使用すると、12:00から2:00の間に、サーバーによってTCP接続がシャットダウンされたというエラーが表示されます。これは完全なメッセージです:

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)

解決策があります。しかし、この方法で試してみると、問題も発生します。今、私はやり方がわかりません。誰かがこの問題に遭遇しますか?

これが私が書いた方法です解決策に従ってください:

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

回答:


160

次のコードを使用してサーバーの切断を処理してみてください。

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

あなたのコードでは、私は後の部分が欠けています connection = mysql.createConnection(db_config);


わかりました、これを試してみます。しかし、どうすればこの状況をシミュレートできますか
jackieLin

1
ヒント:すべてが正常に機能することを確認するために、mysqlサービスを再起動して再接続をテストしています。
kriskodzi 2014

2
あなたは、Ubuntuは、サービスのmysqlの再起動をSUDOに、MySQLサービスを再起動し、状況をシミュレートすることができ@jackieLin
イゴール

1
ありがとう@ user3073745、この問題は再起動によって解決されます
jackieLin 2015年

1
ノード8。*、npm 5.6.0、およびmysql:5.7で完全に機能します...ありがとう!!
JRichardsz

47

このメカニズムの元のユースケースを思い出せません。今日、私は有効なユースケースを考えることができません。

クライアントは、接続が失われたことを検出し、接続を再作成できるようにする必要があります。プログラムロジックの一部が同じ接続を使用して実行されることが重要な場合は、トランザクションを使用します。

tl; dr; この方法は使用しないでください。


実用的な解決策は、MySQLに接続を維持するように強制することです。

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

接続の存在を認識する方法でコードを構造化する必要がないため、接続プールと切断の処理よりもこのソリューションの方が好きです。5秒ごとにクエリを実行すると、接続が維持され、PROTOCOL_CONNECTION_LOST発生しなくなります。

さらに、この方法では、再接続するのではなく、同じ接続を維持できます。これは重要。スクリプトが依存していてLAST_INSERT_ID()、mysql接続が気付かないうちにリセットされた場合はどうなるか考えてみてください。

ただし、これは接続タイムアウト(wait_timeoutおよびinteractive_timeout)が発生しないことを保証するだけです。他のすべてのシナリオでは、予想どおり失敗します。したがって、他のエラーも必ず処理してください。


1
興味がありますが、そのdbクエリをどこに配置しますか?nodejsサーバーの下部にありますか?唯一の問題は、mysqlを使用してユーザーを一度だけ認証してから、rpgゲームの一時ユーザーオブジェクトにデータを保存することです。今日、なぜこのmysqlクローズエラーがランダムに発生したのかわかりません、うーん。私もきちんと接続を閉じています。
NiCk Newman 2015

1
データベースに接続し、オンデマンドで切断する必要があります。このソリューションは、継続的に実行され、データベース接続を常に利用するサービス向けです。
ガジュス2015年

1
コードが説明されているパターン(gist.github.com/gajus/5bcd3c7ec5ddcaf53893に似ている)に従っていることを考えると、どちらもありそうにないようです。これが数千のクエリのうち1〜2回だけ発生した場合は、接続の問題、サーバーの過負荷、またはそれらの線に沿った何かを想定します。
ガジュス2015年

2
それはおそらく史上最悪の提案でした!接続が失敗しないように、データベースをクエリでハンマーで叩くべきだと提案している人はいますか?100人がこれを行うとどうなりますか?または、なぜ10000ではないのか、アプリが気付かない場合は、弱いコードが壊れないように、スレッドを占有せずにMYSQLスレッドプールにスレッドを返す必要があります!この場合、そのようなイベントが発生した場合に再接続する機能を実装します!!これは信じられないことです、それはFBがリードアーキテクトとしてあなたを持っていなかったようなstu ***感謝の神です!!
PatrikForsberg19年

2
私はこのアプローチを推奨しないことを反映するために回答を更新しました。パトリックの頭を上げてくれてありがとう。
ガジュス



1

各クエリで接続を作成して破棄するのは複雑かもしれません。MySQLの代わりにMariaDBをインストールすることにしたとき、サーバーの移行でいくつかの頭痛の種がありました。何らかの理由で、ファイルetc / my.cnfで、パラメーターwait_timeoutのデフォルト値は10秒でした(永続性を実装できない原因になります)。次に、ソリューションは28800、つまり8時間で設定されました。さて、私はこの「güevonada」で誰かを助けてくれることを願っています...私の悪い英語で失礼します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.