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

Javascript 节点mysqljs。如何正确关闭连接,javascript,mysql,node.js,Javascript,Mysql,Node.js,我使用mysqljs通过javascript访问MySQL 我想指出的是,如果只需要一段数据,这个过程似乎工作得很好。 我正在向代码中输入大量数据,作为批处理逐行处理 我创建的连接如下所示: var connection = mysql.createConnection({ //debug: ['ComQueryPacket'], host : dataSource.host, user : dataSource.user, passw

我使用mysqljs通过javascript访问MySQL

我想指出的是,如果只需要一段数据,这个过程似乎工作得很好。 我正在向代码中输入大量数据,作为批处理逐行处理

我创建的连接如下所示:

var connection = mysql.createConnection({
    //debug: ['ComQueryPacket'],
    host        : dataSource.host,
    user        : dataSource.user,
    password: dataSource.password,
    database: dataSource.database
});
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);
         }  
    });
  });
}
我有三个函数可以进行数据库查询

包含SELECT查询的函数如下所示:

var connection = mysql.createConnection({
    //debug: ['ComQueryPacket'],
    host        : dataSource.host,
    user        : dataSource.user,
    password: dataSource.password,
    database: dataSource.database
});
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);
    });
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]]);
}
如果我忽略connection.end(),代码将挂起,数据流将在处理的第一个项目处暂停

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


数据库连接错误:错误:调用quit后无法将查询排队

我将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.
根据文档,我不清楚如何正确处理关闭连接,以便代码能够正确处理

不知道我做错了什么。可以从有使用连接处理数据块经验的人那里得到一些指导,以及如何正确处理关闭连接

注意:
当我尝试连接池时,也会出现类似的问题,因此这不是一个可行的解决方案。

如果使用连接池,则不必手动关闭连接。有一个
.query()
方便的方法。因为您已经在使用
.query()
,所以不要在函数结束时关闭它

这是pool.getConnection()->connection.query()->connection.release()代码流的快捷方式


您正在使用隐式连接。也就是说,您正在尝试查询数据库,而无需先显式连接。这意味着每次运行此行时:

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);
                } 
            });
        });
    });
}
因为这是一个将被反复使用的模式,我建议将其移动到它自己的功能:

if (dataItem){
  dbSearch(dataItem)
    .then((row) => {
        processingfunction(row);
    });
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]]);
}
然后只需调用函数:

if (dataItem){
  dbSearch(dataItem)
    .then((row) => {
        processingfunction(row);
    });
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);
                } 
            });
        });
    });
}

正如我在问题库中提到的,仍然存在同样的问题。除非连接关闭或池连接被破坏,否则代码将挂起。release()并不能阻止它挂起。但不会。这正是导致我在问题中指出的错误的原因。(节点:5864)未处理的PromisejectionWarning:数据库连接错误:错误:在已将握手排队后,无法将握手排队。(节点:5864)未处理的PromisejectionWarning:未处理的承诺拒绝。此错误源于抛出不带catch块的异步函数内部,或者源于未使用.catch()处理的RSE。(拒绝id:1)数据库连接错误:错误:在已将握手排队后,无法将握手排队。在这些调用之前,您是否在其他位置连接到数据库?您可以尝试在executeQuery函数中检查连接状态。这将在尝试连接之前完成。if(connection.threadId)//不要尝试连接。否第一个连接是查询函数。我已禁用“更新”和“插入”,以便了解关闭连接的情况。我已更新我的答案,以便在尝试连接之前包含检查连接的功能。我能理解你的沮丧,因为听起来事情应该是正常的。