节点mysqljs如何正确关闭连接

时间:2019-12-10 02:18:31

标签: javascript mysql node.js

我正在使用mysqljs通过javascript访问MySQL。

我想指出的是,如果只有一条数据,此过程似乎可以正常工作。 我正在将大量数据输入到我的代码中,以批量方式逐行处理。

我这样创建我的连接:

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

我有三个函数可以进行数据库查询。

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

代码在另一个函数中执行:

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

如果我忽略了connection.end(),则代码将挂起,并且数据流将在要处理的第一项上保持住。

如果我将connection.end()放在函数中,则会出现此错误:

数据库连接错误:错误:调用退出后无法使查询入队。

我将connection.end()作为代码的最后一行,一切正常

问题出在更新和插入功能上

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

在函数中使用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.

基于文档,我不清楚如何正确处理关闭连接,以便代码可以正确处理。

不确定我在做什么错。可以从有使用连接经验的人那里得到一些指导来处理数据块以及如何正确处理关闭连接的情况吗?

注意: 当我尝试连接池时也会发生类似的问题,所以这不是可行的解决方案。

2 个答案:

答案 0 :(得分:0)

您使用连接池时,不必手动关闭conn。有一种.query()方便的方法。由于您已经在使用.query(),因此请不要在函数末尾将其关闭。

  

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

答案 1 :(得分:0)

您正在使用隐式连接。意思是,您试图查询数据库而不先显式连接。这意味着您每次运行此行:

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

您不能确定这是连接错误。可能是查询错误。我认为最好是明确创建/销毁您的连接。

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

因为这是一种将反复使用的模式,所以建议将其移至其自身的功能:

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

然后简单地调用函数:

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

要使用连接池,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);
        });
    });
}

这应该可以解决您的问题,但如果不能解决问题,则至少应该通过打破错误条件并将所有与查询相关的代码引入同一功能来帮助缩小可能性。

首先检查连接

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