使用 mysql 和 node.js 的可序列化事务
Posted
技术标签:
【中文标题】使用 mysql 和 node.js 的可序列化事务【英文标题】:Serializable transactions using mysql and node.js 【发布时间】:2014-11-22 21:56:29 【问题描述】:我在使用 node.js 和 mysql 的事务方面遇到问题。问题是我的事务不是独立运行的,即使我将隔离级别设置为“可序列化”。
我设置了以下最小示例来举例说明我的问题。我正在使用带有两个列(id,val)的单个表:
CREATE TABLE `A` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`val` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `A` (`id`, `val`) VALUES (1,0);
请注意,我取消了 InnoDB 表类型,因为它支持事务。
我的 node.js 程序只是从表 A 中的单行读取值,并使用更新语句递增它。 select 语句使用 FOR UPDATE 修饰符来获得对行的锁定。两条sql语句被包装成一个事务,我在一个for循环中执行了其中的10个事务:
var orm = require("orm");
orm.connect("mysql://root@localhost/test", function (err, db)
db.driver.execQuery("SET GLOBAL tx_isolation='SERIALIZABLE';", function (err, data)
for (var i = 0; i < 10; i++)
db.driver.execQuery("START TRANSACTION;", function (err, data)
db.driver.execQuery("SELECT * FROM A FOR UPDATE;", function (err, data)
var value = data[0].val
console.log('reading value: ',value)
db.driver.execQuery("UPDATE A SET val="+value+"+1 WHERE id=1", function (err, data)
console.log('writing value: ', value+1)
db.driver.execQuery("COMMIT;", function (err, data) )
)
)
)
)
)
我希望在运行这段代码之后,存储在表 A 中的值会增加 10。然而,它只是增加了 1。
为了了解发生了什么,我在代码中添加了打印输出。我希望看到打印输出
reading value 0
writing value 1
reading value 1
writing value 2
...
但是我得到了打印输出
reading value 0
reading value 0
...
writing value 1
writing value 1
...
解决问题的一种方法是为每个事务建立一个新的数据库连接,但出于性能原因,我不希望这样做。
有人可以解释发生了什么,以及如何将上述内容更改为 node.js 中事务的工作示例吗?
【问题讨论】:
【参考方案1】:好的,我们找到了使用node-mysql-transaction 包的解决方案(参见下面的代码)。
var mysql = require('mysql');
var transaction = require('node-mysql-transaction');
var trCon = transaction(
connection: [mysql.createConnection,
host : 'localhost',
database : 'test',
user : 'root',
password : 'root',
],
dynamicConnection: 32,
idleConnectionCutoffTime: 1000,
timeout:600
);
for(var i=0;i<10;i++)
trCon.set(function(err, safeCon)
safeCon.query('SELECT * FROM A FOR UPDATE;',[],function(err,result)
if (err) safeCon.rollback()
var val = result[0].val
val += 1
safeCon.query('UPDATE A SET val='+val,[],function(err,result)
if (err) safeCon.rollback(err)
else safeCon.commit();
)
)
)
【讨论】:
以上是关于使用 mysql 和 node.js 的可序列化事务的主要内容,如果未能解决你的问题,请参考以下文章