3

我在我的应用程序中使用node-mysql。我尝试实现SELECT FOR UPDATE但我无法让它正常工作。我遇到的问题类似于下面的代码。下面for循环中的第一个事务没有成功阻塞第二个事务。相反,两个事务同时 SELECT FOR UPDATE 并获得相同的记录。我怎样才能解决这个问题?谢谢!

var testTransaction = function (count) {
  connection.beginTransaction(function(err) {
    if (err) throw err;
    db.query('SELECT * FROM myTable WHERE id = 1 FOR UPDATE', function(err, rows, result) {
      if (err) { 
        connection.rollback(function() {
          throw err;
        });
      }
      connection.query('UPDATE myTable SET myField=? WHERE id=1', (count + 1), function(err, result) {
        if (err) { 
          db.rollback(function() {
            throw err;
          });
        }  
        connection.commit(function(err) {
          if (err) { 
            db.rollback(function() {
              throw err;
            });
          }
          console.log('success!');
        });
      });

    }); 

  });
}

for (var i = 0; i < 2; i++) {
  testTransaction(i);
}
4

2 回答 2

0

您的问题是您使用的是相同的连接。

尝试这样的事情:

var mysql      = require('mysql');
function conn() {
    var connection = mysql.createConnection({
        host     : 'localhost',
        user     : 'user',
        password : 'pass',
        database : 'test'
    });
    return connection;
}

var testTransaction = function (connection,count) {
    connection.beginTransaction(function(err) {
        if (err) throw err;
        connection.query('SELECT * FROM table WHERE id = 1 FOR UPDATE', function(err, rows, result) {
            console.log(rows);
            if (err) {
                connection.rollback(function() {
                    throw err;
                });
            }
            connection.query('UPDATE table SET name=? WHERE id=1', (count + 1), function(err, result) {
                if (err) {
                    connection.rollback(function() {
                        throw err;
                    });
                }
                setTimeout(function(){
                    connection.commit(function(err) {
                        if (err) {
                            connection.rollback(function() {
                                throw err;
                            });
                        }
                        console.log('success!');
                    });
                },2000);
            });

        });

    });
}

for (var i = 0; i < 2; i++) {
    testTransaction(conn(),i);
}

请注意,它为每个事务使用不同的连接。

在命令行 mysql 中,您可以复制类似的内容,方法是打开两个连接,同时发出两个连接,start transaction然后一次尝试该select ... for update命令两次(两次都有效),另一次尝试一次(等待第一次)。

于 2014-09-23T07:30:17.967 回答
0

node-mysql模块中的方法是异步编写的,因此不会阻塞应用程序。如果您没有理由使用循环,那么您只需向您的函数添加一个回调并嵌套执行:

var testTransaction = function(count, callback) {
  connection.beginTransaction(function (err) {
    if (err) throw err;
    db.query('SELECT * FROM myTable WHERE id = 1 FOR UPDATE', function (err, rows, result) {
      if (err) {
        connection.rollback(function() {
          return callback(err);
        });
      }
      connection.query('UPDATE myTable SET myField=? WHERE id=1', (count + 1), function (err, result) {
        if (err) {
          db.rollback(function() {
            return callback(err);
          });
        }
        connection.commit(function (err) {
          if (err) {
            db.rollback(function() {
              return callback(err);
            });
          }
          callback(null);
          console.log('success!');
        });
      });
    });
  });
};

testTransaction(0, function(err) {
  testTransaction(1, function(err) {
    // both operations have completed
  });
});

如果您出于某种原因需要循环异步函数,那么我会看看异步库。

于 2013-10-10T02:54:50.347 回答