简体   繁体   English

节点 mysqljs。 如何正确关闭连接

[英]Node mysqljs. How to properly close connections

I'm using mysqljs to access MySQL with javascript.我正在使用 mysqljs 通过 javascript 访问 MySQL。

I would like to point out that this process seems to work fine if a single piece of data.我想指出,如果单个数据,这个过程似乎工作正常。 I am feeding into my code a large set of data, to be processed line by line as a batch.我在我的代码中输入了大量数据,作为批处理逐行处理。

I create my connection like this:我像这样创建我的连接:

var connection = mysql.createConnection({
    //debug: ['ComQueryPacket'],
    host        : dataSource.host,
    user        : dataSource.user,
    password: dataSource.password,
    database: dataSource.database
});

I have three functions that make database queries.我有三个进行数据库查询的函数。

The function containing the SELECT query is built like this:包含 SELECT 查询的函数是这样构建的:

dbSearch(data){
  var sql = "SELECT * from table where field =? and otherfield=?";
  return new Promise((resolve, reject) => {
    connection.query(sql, [data[0], data[1], (error, results, fields) => {
        if (error){
          console.log(error);
          reject("Database connection error: " + error);
         } else {
          resolve(results);
         }  
    });
  });
}

The code executes in another function:代码在另一个函数中执行:

if (dataItem){
  dbSearch(dataItem)
    .then((row) => {
        processingfunction(row);
    });

If I leave out connection.end() the code hangs and the stream of data is held up at the first item being processed.如果我省略 connection.end() 代码挂起并且数据流被阻止在正在处理的第一个项目。

If I put connection.end() inside the function, i get this error:如果我把 connection.end() 放在函数中,我会收到这个错误:

Database connection error: Error: Cannot enqueue Query after invoking quit.数据库连接错误:错误:调用退出后无法入队查询。

I put connection.end() as the last line of the code, everything works fine我把 connection.end() 作为代码的最后一行,一切正常

The problem though is for the update and insert functions:但问题在于更新和插入功能:

updateRecord(data){
  var sql = "UPDATE table set field=? where id=?";
  return new Promise((resolve, reject) => {
    connection.query(sql, [data[0], data[1], (error, results, fields) => {
     if (error){
      console.log(error);
      reject("Database connection error: " + error);
     } else {
      resolve(results);
     }
    });
  });
}

inputRecord(data){
  var sql = "INSERT INTO table (field1, field2, field3) VALUES(?,?,?)";
  return new Promise((resolve, reject) => {
    connection.query(sql, [data[0], data[1], data[2]], (error, results, fields) => {
      if (error){
        console.log(error);
        reject("Database connection error: " + error);
      } else {
        resolve(results);
      } 
    });
  });
}

With connection.end() in the function I get this error.在函数中使用 connection.end() 我得到这个错误。

Database connection error: Error: Cannot enqueue Query after invoking quit.
(node:40700) UnhandledPromiseRejectionWarning: Database connection error: Error: Cannot enqueue Query after invoking quit.
(node:40700) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:40700) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Based on the documentation, I have no clarity on how to properly handle closing the connection so that the code can process properly.根据文档,我不清楚如何正确处理关闭连接以便代码可以正确处理。

Not sure what I am doing wrong.不知道我做错了什么。 Could use some mentorinng from someone experienced with using the connections to process chunks of data and how to properly handle closing the connections?可以从有使用连接处理数据块经验的人那里获得一些指导,以及如何正确处理关闭连接?

NOTE: A similar problem happens when I try connection pooling, so that was not a workable solution.注意:当我尝试连接池时会发生类似的问题,因此这不是一个可行的解决方案。

You using connection pool, you don't have to close the conn manually.您使用连接池,您不必手动关闭连接。 There is a .query() convenient method.有一个.query()方便的方法。 Since you're already using .query() , don't close it at the end of the function.由于您已经在使用.query() ,请不要在函数结束时关闭它。

This is a shortcut for the pool.getConnection() -> connection.query() -> connection.release() code flow.这是 pool.getConnection() -> connection.query() -> connection.release() 代码流的快捷方式。

var mysql = require('mysql');
var pool  = mysql.createPool({
  connectionLimit : 10,
  host            : 'example.org',
  user            : 'bob',
  password        : 'secret',
  database        : 'my_db'
});

pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
  if (error) throw error;
  console.log('The solution is: ', results[0].solution);
});

You are using an implicit connection.您正在使用隐式连接。 Meaning, you are attempting to query the database without explicitly connecting first.意思是,您试图在没有先显式连接的情况下查询数据库。 This means that each time you run this line:这意味着每次运行此行时:

reject("Database connection error: " + error);

You can't be certain that it was a connection error.您不能确定这是连接错误。 It may have been a query error.可能是查询错误。 I believe it is always best to explicitly create/destroy your connections.我相信明确地创建/破坏你的连接总是最好的。

inputRecord(data){
    var sql = "INSERT INTO table (field1, field2, field3) VALUES(?,?,?)";
    return new Promise((resolve, reject) => {
        connection.connect(function(err){
            if(err) reject("Database connection error: " + error);
            connection.query(sql, [data[0], data[1], data[2]], (error, results, fields) => {
                connection.end(); // Now you are certain a connection was made, and can be terminated
                if (error){
                    console.log(error);
                    reject("Database connection error: " + error);
                } else {
                    resolve(results);
                } 
            });
        });
    });
}

Because this is a pattern that will be used over and over, I would suggest moving it to it's own function:因为这是一个会反复使用的模式,我建议将它移到它自己的函数中:

executeQuery(query, params){
    return new Promise((resolve, reject) => {
        connection.connect(function(err){
            if(err) reject("Database connection error: " + error); // Connection error with certainty
            connection.query(query, params, (error, results, fields) => {
                connection.end(); // Now you are certain a connection was made, and can be terminated
                if (error){
                    console.log(error);
                    reject("Database query error: " + error);  // Query error
                } else {
                    resolve(results);
                } 
            });
        });
    });
}

And then simply call the function:然后简单地调用函数:

inputRecord(data){
    var sql = "INSERT INTO table (field1, field2, field3) VALUES(?,?,?)";
    return executeQuery(sql,[data[0],data[1],data[2]]);
}

updateRecord(data){
    var sql = "UPDATE table set field=? where id=?";
    return executeQuery(sql,[data[0],data[1]]);
}

dbSearch(data){
    var sql = "SELECT * from table where field =? and otherfield=?";
    return executeQuery(sql,[data[0],data[1]]);
}

To use connection pooling, executeQuery would become:要使用连接池,executeQuery 将变为:

executeQuery(query, params){
    return new Promise((resolve, reject) => {
        pool.query(query, params,function(err,res){ // shortcut for connect, query,end - no need to terminate the connection
            if(err) reject(err);
            else    resolve(res);
        });
    });
}

This should solve your problem, but if not, it should at least help narrow down the possibilities by breaking out the error conditions and bringing all query related code into the same function.这应该可以解决您的问题,但如果没有,它至少应该通过打破错误条件并将所有与查询相关的代码放入同一函数来帮助缩小可能性。

Checking for connection first首先检查连接

getConnection(){
   return new Promise((resolve, reject) => {
       if(connection.state === 'connected') resolve(connection);
       else {
            connection.connect(function(err) => {
                if(err) reject ("Connection error: " + error);
                else resolve(connection);
            });
       }
    });
 }

 executeQuery(query, params){

    return new Promise((resolve, reject) => {
        getConnection().then(connection =>{
            connection.query(query, params, (error, results, fields) => {
                connection.end(); // Now you are certain a connection was made, and can be terminated
                if (error){
                    console.log(error);
                    reject("Database query error: " + error);  // Query error
                } else {
                    resolve(results);
                } 
            });
        });
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM