92

次のコードを実装しました。

module.exports = {
    getDataFromUserGps: function(callback)
    {
        connection.connect();
        connection.query("SELECT * FROM usergps", 
            function(err, results, fields) {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        ); 
        connection.end();
    },
    loginUser: function(login, pass, callback)
    {
        connection.connect();
        connection.query(
            "SELECT id FROM users WHERE login = ? AND pass = ?",
            [login, pass],
            function(err, results, fields) 
            {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        ); 
        connection.end();
    },
    getUserDetails: function(userid, callback)
    {
        connection.connect();
        connection.query(
            "SELECT * FROM userProfilDetails LEFT JOIN tags ON userProfilDetails.userId = tags.userId WHERE userProfilDetails.userid = ?",
            [userid],
            function(err, results, fields)
            {
                if (err) return callback(err, null);
                return callback(null, results);
            }
        );
        connection.end();
    },
    addTags: function(userId, tags)
    {
        connection.connect();
        connection.query(
            "INSERT INTO tag (userId, tag) VALUES (?, ?)",
            [userId, tags],
            function(err, results, fields)
            {
                if (err) throw err;
            }
        )
        connection.end();
    }
}

すべてが初めてうまく機能します。クエリを2回目に「使用」したい場合、次のエラーが発生します。

Cannot enqueue Handshake after invoking quit

.end()接続しないようにしましたが、役に立ちませんでした。

この問題を解決するにはどうすればよいですか?

4

10 に答える 10

261

node-mysqlモジュールを使用している場合は、.connectと.endを削除するだけです。自分で問題を解決しました。どうやら彼らはまたバグがある彼らの最後の反復で不必要なコードを押し込んだ。createConnection呼び出しをすでに実行している場合は、接続する必要はありません。

于 2013-01-09T21:47:40.750 に答える
60

によると:

TL; DRcreateConnection切断するたびにメソッドを呼び出して、新しい接続を確立する必要があります。

注: Webリクエストを処理している場合は、すべてのリクエストで接続を終了するべきではありません。サーバーの起動時に接続を作成し、接続/クライアントオブジェクトを使用して常にクエリを実行するだけです。エラーイベントをリッスンして、サーバーの切断を処理したり、再接続したりすることができます。ここに完全なコード 。


から:

それは言う:

サーバーが切断されます

ネットワークの問題、サーバーのタイムアウト、またはサーバーのクラッシュにより、MySQLサーバーへの接続が失われる可能性があります。これらのイベントはすべて致命的なエラーと見なされ、が発生しerr.code = 'PROTOCOL_CONNECTION_LOST'ます。詳細については、「エラー処理」セクションを参照してください。

このような予期しない切断を処理する最良の方法を以下に示します。

function handleDisconnect(connection) {
  connection.on('error', function(err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
      throw err;
    }

    console.log('Re-connecting lost connection: ' + err.stack);

    connection = mysql.createConnection(connection.config);
    handleDisconnect(connection);
    connection.connect();
  });
}

handleDisconnect(connection);

上記の例でわかるように、接続の再接続は、新しい接続を確立することによって行われます。一度終了すると、既存の接続オブジェクトを意図的に再接続することはできません。

プールを使用すると、切断された接続がプールから削除され、次のgetConnection呼び出しで作成される新しい接続のためのスペースが解放されます。


接続が必要になるたびに、初期化関数がハンドラーを自動的に追加するように関数を微調整しました。

function initializeConnection(config) {
    function addDisconnectHandler(connection) {
        connection.on("error", function (error) {
            if (error instanceof Error) {
                if (error.code === "PROTOCOL_CONNECTION_LOST") {
                    console.error(error.stack);
                    console.log("Lost connection. Reconnecting...");

                    initializeConnection(connection.config);
                } else if (error.fatal) {
                    throw error;
                }
            }
        });
    }

    var connection = mysql.createConnection(config);

    // Add handlers.
    addDisconnectHandler(connection);

    connection.connect();
    return connection;
}

接続の初期化:

var connection = initializeConnection({
    host: "localhost",
    user: "user",
    password: "password"
});

マイナーな提案:これはすべての人に当てはまるわけではありませんが、スコープに関連するマイナーな問題に遭遇しました。OPがこの編集が不要であると感じた場合、OPはそれを削除することを選択できます。私にとっては、の行を変更する必要がinitializeConnectionありvar connection = mysql.createConnection(config);ました。

connection = mysql.createConnection(config);

その理由connectionは、がプログラム内のグローバル変数である場合、以前の問題はconnection、エラー信号を処理するときに新しい変数を作成していたことでした。しかし、私のnodejsコードでは、同じグローバルconnection変数を使用してクエリを実行し続けたため、メソッドconnectionのローカルスコープで新しい変数が失われていました。initalizeConnectionただし、変更では、グローバルconnection変数が確実にリセットされます。これは、次のような問題が発生している場合に関連する可能性があります。

致命的なエラーの後にクエリをキューに入れることができません

接続を失った後にクエリを実行しようとした後、正常に再接続しました。これはOPによるタイプミスだったかもしれませんが、明確にしたかっただけです。

于 2013-05-03T18:58:58.447 に答える
23

私も同じ問題を抱えていて、Googleが私をここに導きました。を削除するだけでは正しくないという@Ataに同意しend()ます。さらにグーグルした後、私は使用poolingすることがより良い方法だと思います。

node-プーリングに関するmysqlドキュメント

こんな感じです:

var mysql = require('mysql');
var pool  = mysql.createPool(...);

pool.getConnection(function(err, connection) {
    connection.query( 'bla bla', function(err, rows) {
        connection.release();
    });
});
于 2013-09-04T10:16:28.763 に答える
7

関数内でconnect()とend()を行わないでください。これにより、関数を繰り返し呼び出すと問題が発生します。接続のみを行う

var connection = mysql.createConnection({
      host: 'localhost',
      user: 'node',
      password: 'node',
      database: 'node_project'
    })

connection.connect(function(err) {
    if (err) throw err

});

一度、その接続を再利用します。

関数内

function insertData(name,id) {

  connection.query('INSERT INTO members (name, id) VALUES (?, ?)', [name,id], function(err,result) {
      if(err) throw err
  });


}
于 2017-07-10T12:20:34.790 に答える
7

AWSLambda関数

connection.destroy()でmysql.createPool()を使用します

このように、新しい呼び出しは確立されたプールを使用しますが、関数の実行を維持しません。プーリングのメリットを十分に享受することはできませんが(新しい接続ごとに既存の接続ではなく新しい接続を使用します)、2回目の呼び出しで、前の接続を最初に閉じなくても新しい接続を確立できます。

それにかんするconnection.end()

これにより、後続の呼び出しでエラーがスローされる可能性があります。呼び出しは後で再試行して機能しますが、遅延が発生します。

についてmysql.createPool()_connection.release()

Lambda関数は、接続が開いたままであるため、スケジュールされたタイムアウトまで実行を続けます。

コード例

const mysql = require('mysql');

const pool = mysql.createPool({
  connectionLimit: 100,
  host:     process.env.DATABASE_HOST,
  user:     process.env.DATABASE_USER,
  password: process.env.DATABASE_PASSWORD,
});

exports.handler = (event) => {
  pool.getConnection((error, connection) => {
    if (error) throw error;
    connection.query(`
      INSERT INTO table_name (event) VALUES ('${event}')
    `, function(error, results, fields) {
      if (error) throw error;
      connection.destroy();
    });
  });
};
于 2019-02-28T23:47:35.683 に答える
2

使用の代わりにconnection.connect();-

if(!connection._connectCalled ) 
{
connection.connect();
}

すでに呼び出されている場合はconnection._connectCalled =true
&は実行されませんconnection.connect();

-使用しないでくださいconnection.end();

于 2018-08-17T09:48:41.960 に答える
1

この問題は私のものと似ていると思います。

  1. MySQLに接続する
  2. MySQLサービスを終了します(ノードスクリプトを終了しないでください)
  3. MySQLサービスを開始し、ノードはMySQLに再接続します
  4. DBのクエリ->FAIL(致命的なエラーの後でクエリをエンキューできません。)

私は、promise(q)を使用して新しい接続を再作成することにより、この問題を解決しました。

mysql-con.js

'use strict';
var config          = require('./../config.js');
var colors          = require('colors');
var mysql           = require('mysql');
var q               = require('q');
var MySQLConnection = {};

MySQLConnection.connect = function(){
    var d = q.defer();
    MySQLConnection.connection = mysql.createConnection({
        host                : 'localhost',
        user                : 'root',
        password            : 'password',
        database            : 'database'
    });

    MySQLConnection.connection.connect(function (err) {
        if(err) {
            console.log('Not connected '.red, err.toString().red, ' RETRYING...'.blue);
            d.reject();
        } else {
            console.log('Connected to Mysql. Exporting..'.blue);
            d.resolve(MySQLConnection.connection);
        }
    });
    return d.promise;
};

module.exports = MySQLConnection;

mysqlAPI.js

var colors          = require('colors');
var mysqlCon        = require('./mysql-con.js');
mysqlCon.connect().then(function(con){
   console.log('connected!');
    mysql = con;
    mysql.on('error', function (err, result) {
        console.log('error occurred. Reconneting...'.purple);
        mysqlAPI.reconnect();
    });
    mysql.query('SELECT 1 + 1 AS solution', function (err, results) {
            if(err) console.log('err',err);
            console.log('Works bro ',results);
    });
});

mysqlAPI.reconnect = function(){
    mysqlCon.connect().then(function(con){
      console.log("connected. getting new reference");
        mysql = con;
        mysql.on('error', function (err, result) {
            mysqlAPI.reconnect();
        });
    }, function (error) {
      console.log("try again");
        setTimeout(mysqlAPI.reconnect, 2000);
    });
};

これがお役に立てば幸いです。

于 2015-02-01T22:17:32.853 に答える
0

解決策:このエラーを防ぐには(AWS LAMBDAの場合):

「Nodejsイベントループ」を終了するには、接続を終了してから再接続する必要があります。コールバックを呼び出す次のコードを追加します。

connection.end( function(err) {
        if (err) {console.log("Error ending the connection:",err);}

       //  reconnect in order to prevent the"Cannot enqueue Handshake after invoking quit"

         connection = mysql.createConnection({
                host     : 'rds.host',
                port     :  3306,
                user     : 'user',
               password : 'password',
               database : 'target database'

               });
        callback(null, {
            statusCode: 200,
            body: response,

        });
    });
于 2018-04-20T01:26:20.717 に答える
0

ラムダを取得しようとしている場合、ハンドラーをで終了するとcontext.done()ラムダが終了することがわかりました。その1行を追加する前は、タイムアウトするまで実行されます。

于 2019-01-18T23:14:36.017 に答える
0

デバッグを使用できます:false、

例://mysql接続

var dbcon1 = mysql.createConnection({
      host: "localhost",
      user: "root",
      password: "",
      database: "node5",
      debug: false,
    });
于 2019-06-07T08:34:12.520 に答える