पद छोड़ने के बाद हैंडशेक को लागू नहीं कर सकते


83

मैंने निम्नलिखित कोड लागू किया है:

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

पहली बार में ही सब कुछ बढ़िया काम करता है। अगर मैं दूसरी बार क्वेरी को "उपयोग" करना चाहता हूं तो मुझे निम्नलिखित त्रुटि मिलेगी:

Cannot enqueue Handshake after invoking quit

मैं .end()कनेक्शन के लिए नहीं की कोशिश की है, लेकिन यह मदद नहीं की।

मैं इस समस्या को कैसे हल कर सकता हूं?


2
क्या आप कम से कम प्रश्न को बंद कर सकते हैं?
एंड्रयू राइन

मेरे लिए, त्रुटि तब हुई थी जब मैं एक कनेक्शन खोलने की कोशिश कर रहा था, जबकि एक खुला है (यानी, दो कनेक्शन हैं। कनेक्ट करें) () एक दूसरे के बगल में कॉल करते हैं
3

कॉलबैक फ़ंक्शन के connection.endअंदर कॉल करें connection.queryक्योंकि यह एसिंक्रोनस रूप से निष्पादित होगा।
अर्जुन सिंह

जवाबों:


244

यदि आप नोड- mysql मॉड्यूल का उपयोग कर रहे हैं, तो बस .connect और .end को हटा दें। बस समस्या खुद हल हो गई। जाहिरा तौर पर वे अपने पिछले चलना में अनावश्यक कोड में धकेल दिया है कि यह भी बग है। यदि आपको पहले ही क्रिप्‍टोकरेंसी कॉल चला दिया है तो आपको कनेक्‍ट करने की आवश्‍यकता नहीं है


22
यह सबसे खराब उत्तर है जो मुझे मिला है! जब आप एक कनेक्शन बनाने, और यह खोलता है, अब, लगता है कि हम एक समारोह में एक mysql नोड बनाने के लिए, हर बार जब समारोह कहा जाता है, यह बना सकते हैं और खुले कनेक्शन पकड़, एक कम समय के बाद, आप mysql कनेक्शन की अधिकतम सीमा तक पहुँच पाने के
अता

5
फिर आप गलत कर रहे हैं। आप कनेक्शन का पुन: उपयोग करने वाले हैं
एंड्रयू राइन

6
@ata नोड- mysql एक कनेक्शन पूल को लागू करता है। आपको प्रत्येक अनुरोध के साथ कनेक्शन ऑब्जेक्ट को नष्ट नहीं करना चाहिए क्योंकि यह वास्तविक अनुरोध नहीं है। यह भी सुनिश्चित नहीं है कि आपकी टिप्पणी क्यों उठ रही है। स्पष्ट रूप से लोग डॉक्स नहीं पढ़ रहे हैं
एंड्रयू राइन

5
यदि आप अंब के लंबो में चल रहे हैं, तो कनेक्शन बंद न करने पर लैंबडा टाइमिंग करेगा। इसलिए ये सभी सुझाव मदद नहीं करते हैं। मैंने इस मुद्दे पर दिन बिताए हैं।
जोसेफ बोलाडे कैक्सटन-इदोवू

धन्यवाद जो मेरे लिए काम करता है। @ XP1 के नीचे का उत्तर इस व्यवहार पर अधिक विवरण देता है।
केइटेलडॉग

55

इसके अनुसार:

TL; DR आपको createConnectionहर वियोग के बाद विधि को कॉल करके एक नया कनेक्शन स्थापित करना होगा ।

तथा

नोट: यदि आप वेब अनुरोधों की सेवा कर रहे हैं, तो आपको हर अनुरोध पर कनेक्शन समाप्त नहीं करने चाहिए। बस सर्वर स्टार्टअप पर एक कनेक्शन बनाएं और हर समय क्वेरी करने के लिए कनेक्शन / क्लाइंट ऑब्जेक्ट का उपयोग करें। सर्वर डिसकनेक्शन को संभालने के लिए और पुन: कनेक्ट करने के लिए आप एरर इवेंट पर सुन सकते हैं। पूर्ण कोड यहाँ


से:

इसे कहते हैं:

सर्वर डिस्कनेक्ट करता है

नेटवर्क समस्याओं, सर्वर टाइमिंग के कारण, या सर्वर क्रैश होने के कारण आप 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);

जैसा कि आप ऊपर दिए गए उदाहरण में देख सकते हैं, एक कनेक्शन को फिर से जोड़ना एक नया कनेक्शन स्थापित करके किया जाता है। एक बार समाप्त होने के बाद, एक मौजूदा कनेक्शन ऑब्जेक्ट को डिज़ाइन द्वारा पुन: कनेक्ट नहीं किया जा सकता है।

पूल के साथ, डिस्कनेक्ट किए गए कनेक्शन को पूल से मुक्त करके एक नया कनेक्शन अगले गेटकनेक्शन कॉल पर बनाया जाएगा।


मैंने फ़ंक्शन को इस तरह से ट्वीक किया है कि हर बार कनेक्शन की आवश्यकता होती है, एक शुरुआती फ़ंक्शन हैंडलर को स्वचालित रूप से जोड़ता है:

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"
});

मामूली सुझाव: यह सभी के लिए लागू नहीं हो सकता है लेकिन मैं गुंजाइश से संबंधित एक छोटी सी समस्या में चला गया। यदि ओपी को लगता है कि यह संपादन अनावश्यक था, तो वह इसे हटाने का विकल्प चुन सकता है। मेरे लिए, मुझे एक लाइन बदलनी थी initializeConnection, जो कि var connection = mysql.createConnection(config);सिर्फ और सिर्फ करने के लिए थी

connection = mysql.createConnection(config);

इसका कारण यह है कि यदि connectionआपके कार्यक्रम में एक वैश्विक चर है, तो इससे पहले मुद्दा यह था कि आप connectionत्रुटि संकेत को संभालने के दौरान एक नया चर बना रहे थे । लेकिन मेरे नोडज कोड में, मैं connectionप्रश्नों को चलाने के लिए उसी वैश्विक चर का उपयोग करता रहा , इसलिए विधि connectionके स्थानीय दायरे में नया खो जाएगा initalizeConnection। लेकिन संशोधन में, यह सुनिश्चित करता है कि वैश्विक connectionचर रीसेट हो गया है यह प्रासंगिक हो सकता है यदि आप एक समस्या के रूप में जाना जाता है

घातक त्रुटि के बाद क्वेरी को संलग्न नहीं कर सकता

कनेक्शन खोने के बाद क्वेरी करने की कोशिश करने और फिर सफलतापूर्वक पुनः जोड़ने के बाद। यह ओपी द्वारा एक टाइपो हो सकता है, लेकिन मैं सिर्फ स्पष्ट करना चाहता था।


1
बहुत बढ़िया कोड है, लेकिन मेरी स्क्रिप्ट अभी भी बाहर निकलने के लिए लगता है (कोड 8) 90 सेकंड के बाद भी addDisconectHandler दिनचर्या में प्रवेश करने के बिना। विचार?
ईएमसी

शानदार जवाब, मैं एक रिफ्लेक्टर के बाद पूलिंग के लिए गया था, लेकिन यह एक उत्कृष्ट विकल्प है।
पोग्रिंडिस

अच्छा जवाब धन्यवाद। यह आधिकारिक डॉक का हिस्सा होना चाहिए (और नोड-mysql द्वारा नियंत्रित किया जाता है, डेवलपर नहीं)।
स्काउ

1
यह एक शानदार उत्तर है, लेकिन मेरे पास मेरे लिए काम करने के लिए एक सुझाव / ट्वीक है, जिसकी मुझे आवश्यकता है। मुझे यकीन नहीं है कि यह हर किसी के लिए आवश्यक होगा, लेकिन इससे निश्चित रूप से मुझे मदद मिली। आप संपादन को हटाने का चयन कर सकते हैं यदि आपको लगता है कि यह अनावश्यक है, तो इस प्रकार आपकी मदद के लिए धन्यवाद।
क्रिस गोंग

23

मुझे भी यही समस्या थी और गूगल ने मुझे यहां तक ​​पहुंचाया। मैं @ एटा से सहमत हूं कि सिर्फ हटाना ही सही नहीं है end()। आगे Googling के बाद, मुझे लगता है कि उपयोग poolingकरना बेहतर तरीका है।

नोड- mysql पूलिंग के बारे में डॉक्टर

ऐसी बात हे:

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

pool.getConnection(function(err, connection) {
    connection.query( 'bla bla', function(err, rows) {
        connection.release();
    });
});

7

फ़ंक्शन के अंदर कनेक्ट न करें () और अंत ()। इससे फ़ंक्शन को बार-बार कॉल करने पर समस्या होगी। केवल संबंध बनाओ

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


}

5

AWS लाम्बा के कार्य

कनेक्शन के साथ mysql.createPool () का उपयोग करें ।estroy ()

इस तरह, नए इनवोकेशन स्थापित पूल का उपयोग करते हैं, लेकिन फ़ंक्शन को चालू नहीं रखते हैं। भले ही आपको पूलिंग का पूरा लाभ नहीं मिलता (प्रत्येक नया कनेक्शन मौजूदा के बजाय एक नया कनेक्शन का उपयोग करता है), यह ऐसा करता है ताकि दूसरा आह्वान पहले बंद किए बिना पिछले कनेक्शन के बिना एक नया कनेक्शन स्थापित कर सके।

के बारे में connection.end()

यह एक त्रुटि को फेंकने के लिए बाद के आह्वान का कारण बन सकता है। आह्वान अभी भी बाद में फिर से प्रयास करेगा और काम करेगा, लेकिन देरी के साथ।

के संबंध mysql.createPool()मेंconnection.release()

लैंबडा फ़ंक्शन निर्धारित समय समाप्त होने तक चलता रहेगा, क्योंकि अभी भी एक खुला कनेक्शन है।

कोड उदाहरण

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

मुझे AWS लैम्ब्डा फंक्शन के रूप में एक NodeJS स्क्रिप्ट मिली है। यह एक एज़्योर एपीआई पिंग करता है जो एक बार में 100 रिकॉर्ड देता है, एक "अगला" URL के साथ अगले 100 को पुनः प्राप्त करने के लिए, डेटा सेट के अंत तक। इसलिए मेरे INSERT फ़ंक्शन को कई बार कॉल किया जाता है। जब तक मैं कनेक्शन को हटा नहीं देता, तब तक मुझे "इनवॉइस इनकाउंटर के बाद हैंडशेक" नहीं मिल रहा था, जब तक कि मैंने कनेक्शन को हटा नहीं दिया था। क्या इसके बजाय यहाँ एक पूल का उपयोग करना अधिक समझ में आता है? मुझे यकीन नहीं है कि जब मैं "connection.end ()" कहूंगा, जब अंतिम डेटा सेट एपीआई से वापस आ जाएगा ...
Shafique

2

की inplace connection.connect();उपयोग -

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

अगर यह पहले से ही कहा जाता है connection._connectCalled =true,
और यह निष्पादित नहीं करेगा connection.connect();

नोट - उपयोग न करेंconnection.end();


1

मुझे लगता है कि यह मुद्दा मेरे जैसा है:

  1. MySQL से कनेक्ट करें
  2. MySQL सेवा समाप्त करें (नोड स्क्रिप्ट नहीं छोड़नी चाहिए)
  3. MySQL सेवा शुरू करें, नोड MySQL में फिर से जुड़ता है
  4. DB की क्वेरी -> विफल (घातक त्रुटि के बाद क्वेरी को गणना नहीं कर सकता।)

मैंने वादों (क्यू) के उपयोग के साथ एक नया कनेक्शन पुनः बनाकर इस मुद्दे को हल किया।

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

आशा है कि ये आपकी मदद करेगा।


0

समाधान: इस त्रुटि को रोकने के लिए (AWS LAMBDA के लिए):

"नोड्स इवेंट लूप" से बाहर निकलने के लिए आपको कनेक्शन समाप्त करना होगा, और फिर पुन: कनेक्ट करना होगा। कॉलबैक आह्वान करने के लिए अगला कोड जोड़ें:

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,

        });
    });

लंबोदा समारोह के हर आह्वान का परिणाम तब नहीं होगा जब एक खुला mysql कनेक्शन होगा? यह स्वीकृत उत्तर को करने का एक और तरीका है जो एक अच्छा विचार नहीं है
ब्रायन मैक्कल

1
नहीं। जब आप कनेक्शन कहते हैं। लूप खत्म हो जाता है, लेकिन डेटाबेस का कनेक्शन "क्विटिंग कनेक्शन" स्थिति में रहता है। जब आप एक नया कनेक्शन खोलने की कोशिश करते हैं, तो आपको हमेशा त्रुटि "छोड़ना शुरू करने के बाद हैंडशेक नहीं कर सकता है", इसलिए, वास्तव में अतिरिक्त क्रिएटनक्शन, इस असफलता को प्राप्त करता है, और अगला कनेक्शन विफल नहीं होता है। यह केवल इस समस्या की सवारी करने का एक तरीका है, वास्तव में, mysql मॉड्यूल को एक क्लीनर कनेक्शन समाप्त करने की आवश्यकता है।
जॉर्ज वाल्टर

0

यदि आप एक लैम्ब्डा प्राप्त करने की कोशिश कर रहे हैं, तो मैंने पाया कि हैंडलर context.done()को समाप्त करने के लिए लैम्बडा को समाप्त करना है। उस 1 लाइन को जोड़ने से पहले, यह बस चलेगी और तब तक चलेगी जब तक यह समय समाप्त नहीं हो जाता।


कृपया इसके लिए कोड उदाहरण?
शफिक

0

आप डिबग का उपयोग कर सकते हैं: गलत,

उदाहरण: // mysql कनेक्शन

var dbcon1 = mysql.createConnection({
      host: "localhost",
      user: "root",
      password: "",
      database: "node5",
      debug: false,
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.