在nodejs中循环mysql查询

时间:2014-11-14 20:13:03

标签: mysql node.js

我在几个网页上抓桌子并用表格中的项目更新MYSQL数据库。我正在使用MYSQL模块,并在循环遍历所有行时遇到各种错误。这是函数的一次迭代:

  var connection = mysql.createConnection(opts);
  connection.connect();

function updateDB(o,lang){
  var tbl_name = "news_"+lang;
  o.forEach(function(entry,index,arr){
      var sql1 = "SELECT * FROM "+tbl_name+" WHERE url = '"+htmlencode.htmlEncode(entry.url)+"' and omit = '1'";
      connection.query(sql1, function(err, rows, fields) {
        connection.end();
        if (err){
          console.log("can't run query=" + sql1 +"\n Error="+err);
        }
        else{
          console.log('ROWS:',rows);
          // if rows.length = 0 then update table with new info here...
        }
      });
  }); 
};

如果我注释掉connection.end()行,这实际上是有效的,但是连接永远不会结束,并且进程永远保持活着。我将它作为批处理脚本运行,所以我需要它优雅地结束。在connection.end()到位后,我得到"Cannot enqueue Quit after invoking quit."

我尝试使用async.series将connection.end置于最终回调中,但仍然无效。我尝试使用池和不同的代码迭代来尝试使某些东西起作用。我最后使用mysql模块并想知道是否还有另一个可以更好地工作。

1 个答案:

答案 0 :(得分:0)

看起来您只有一个连接而且您正在使用.forEach,这不是异步友好的。

您应该使用连接池和async.eachLimit来控制并发。

var pool = mysql.createPool({
  host: process.env.MYSQL_HOST,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASS,
  database: process.env.MYSQL_NAME,
  connectionLimit: 10
});

function updateDB(o,lang){
  // submit as a sub-function to get the `lang` closure
  // this could probably be organized a different way, but this fits your structure
  function submit(entry, callback) {
    var tbl_name = "news_"+lang;
    var sql = [
      'SELECT * FROM ' + tbl_name,
      ' WHERE url="?" and omit="1"'
    ].join('');
    pool.getConnection(function(err, connection) {
      if(err) return callback(err);
      connection.query(sql, [entry.url], function(err, results) {
        connection.release();
        if(err) return callback(err);
        console.log('ROWS:',results);
      });
    });
  }

  async.eachLimit(o, 10, submit, function(err) {
    if(err) throw err;
    console.log('Done processing');
  });
}

即使您不需要多个连接,也应该几乎总是使用池。池将根据需要重新创建连接。这非常方便,因为您的连接可能会因mysql超时,网络问题和任何其他原因而死亡。当您使用池时,您的代码将更加健壮。

如果您只想一次执行一个查询,只需将第二个参数更改为async.eachLimit1