关于nodejs 处理事务的问题
发布于 10 年前 作者 xbl1949 28233 次浏览 最后一次编辑是 8 年前

最近在写一个网站需要用到事务,node-mysql 是支持事务的,也没有问题,如下:

// 从链接池里得到connection
pool.getConnection(function(err, connection) {
    if(err) {
        console.error('mysql 链接失败');
        return callback(err, null);
    }
    // 开始事务
    connection.beginTransaction(function(err) {
    	if(err) {
    		throw err;
    	}
    	async.parallel([
    		function(callback) {
		    	connection.query("执行sql,比如是添加任务", callback);
		    },
		    function(callback) {
		    	connection.query("执行sql,添加任务时间区段", callback);
			}
		], function(err, result) {
			if(err) {
				connection.rollback(function() {
					throw err;
				});
				return ;
			}
			// 提交事务
			connection.commit(function(err) {
				if (err) { 
					connection.rollback(function() {
					throw err;
					});
				}
				console.log('success!');
			});
		});
    });
});

我们知道,使用的事务的时候必须所有的操作都在一个connection 上, 在这段代码里插入了一条任务,和任务的时间区段 但是生产的代码不可能是这个样子,对任务和时间区段的操作都会有个子的service,


mysqlUtil.beginTransaction(function(err) {
	if(err) {
		throw err;
	}
	async.parallel([
		function(callback) {
	    	taskService.add(task, callback);
	    },
	    function(callback) {
	    	segment.add(segment, callback);
		}
	], function(err, result) {
		if(err) {
			mysqlUtil.rollback(function() {
				throw err;
			});
			return ;
		}

		mysqlUtil.commit(function(err) {
			if (err) { 
				mysqlUtil.rollback(function() {
				throw err;
				});
			}
			console.log('success!');
		});
	});
});

每一个service 都会自己从pool 里自己得到connection,问题就出现了,我没有办法保证让启动是的connection 和service 使用的connection是一个,各位大牛有什么好的办法吗?

14 回复

可以显式地从 node-mysql 中取出一个 connection 来的吧?

不是无法得到connection,而是无法保证使用connection是同一个,不知道如何做,完全没思路 又不想每一个service都带一个connection的参数

事务推荐使用 bearcat-dao 对 node-mysql 进行了 AOP 事务封装

bearcat-dao 里面通过在 dao 方法显示的传递一个 transactionStatus 来保证事务是在同一个 connection 里面的

bearcat-dao 看起来还是有些复杂,能不能不用它就可以帮我把问题解决了呢

@xbl1949 你直接用 node-mysql 更加复杂把,代码耦合很严重,业务逻辑代码和事务代码夹在一起,让你无所是从,可以看看 bearcat-todo, 一个简单的todo的例子,用了bearcat-dao

一个事务里的sql是顺序执行的 虽然没有用过node-mysql,但一看到async.parallel,而且两条sql不是互相嵌套在回调函数里,就知道这是并行执行的,就不会在一个事务里,也就不会在一个connection里

这段代码是有点问题,假设是顺序执行的,也同样不在同一个connection,service 会各自从连接池里得到connection

楼主你好,我也碰到了这个问题,想问一下您是怎么解决的?

有一个方法是, mysqlUtil获取一个connection, 然后调用service的时候将此connection作为参数传递,利用这个connection执行sql操作,不知道可不可行?

还有就是设置一个单例的connection,然后在需要事务操作的时候,获取这个单例使用

我不明白你们怎么会有这样的问题,在service中,首先拿联接,然后再把联接传到module中拿数据。不管拿多少数据,都是一个联接 From Noder

你们处理mysql数据库事务都用这种方式吗,如果事务中还有逻辑,或者前面一个sql执行的结果是后面一个sql执行的条件,这样的怎么处理呢,说简单点:一个包含事务的存储过程,怎么用node来做,也用这种方式吗?

刚刚封装了一个操作mysql的库,基于node-mysql. 支持事务,每一步的返回值可以用作后面一步的条件。 可用于generator/yield,async/await 戳这里

回到顶部