jef*_*eon 12 javascript mysql database transactions node.js
我正在使用express和node-mysql驱动程序在node.js上构建一个应用程序.当我需要进行一系列数据库插入/更新时,我的应用程序中有几种情况.我希望它们在一个事务中,如果第二个或第三个失败,则先前的插入完全回滚.
目前,我这样做的方式是让某种中间件START TRANSACTION在请求到达时执行.在处理请求的过程中,如果抛出任何错误,我会发现此错误,然后执行操作ROLLBACK.如果没有发生错误,我会COMMIT在将响应发送到浏览器之前执行.
但是,我现在担心当多个用户同时访问应用程序时这不起作用,因为如果另一个请求试图开始它自己的事务,MySQL会强制提交 START TRANSACTION!我目前只使用单个节点实例,并为所有请求使用单个MySQL连接.
如果我的担忧有效,有人可以建议我吗?如何获得交易支持?
查看https://github.com/bminer/node-mysql-queues
我为node-mysql实现了一个小包装器来支持事务和多个语句.它尚未经过测试,并未准备好生产......但它将在几天内完成.:)
更新:我现在已经非常彻底地测试了这个库...应该很好!
小智 5
根据您的事务的复杂程度,您可能会遇到一些丑陋的嵌套,试图将您的查询从Node排队,这可能会引入丑陋的变量范围问题.
你可以做的反而是写一个存储过程并结束它SELECT荷兰国际集团成功/失败的标志,然后与查询程序节点MySQL的你将一个SELECT查询.以下是存储过程的外观:
DELIMITER //
DROP PROCEDURE IF EXISTS MyProcedure //
CREATE PROCEDURE MyProcedure(IN param1 VARCHAR/*, My, Parameters, ... */)
BEGIN
DECLARE EXIT HANDLER FOR NOT FOUND, SQLWARNING, SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 0 AS res;
END;
START TRANSACTION;
# My Transaction ...
COMMIT;
SELECT 1 AS res;
END //
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
您的节点代码看起来像这样:
var mysql = require('mysql');
var client = mysql.createClient({
host : '127.0.0.1',
user : 'username',
password: 'password'
});
client.query('USE mydatabase');
var myParams = "'param1', 'param2', ... ";
client.query("CALL MyProcedure(" + myParams + ")", function(err, results, fields) {
if (err || results[0].res === 0) {
throw new Error("My Error ... ");
} else {
// My Callback Stuff ...
}
});
Run Code Online (Sandbox Code Playgroud)
您需要创建一个客户端池,或者以其他方式确保两个不同的页面不会在同一连接上散布命令(至少在其中任何一个页面处于事务中时)。
由于您希望根据先前命令的结果有条件地进行回滚,因此您需要通过回调将数据库调用链接在一起,而不是依赖于 node-mysql 排队行为。这将打开一个窗口,供其他页面进入,并按照您的建议对同一连接上的操作进行排队。
您可以创建和管理自己的队列,但这最终会序列化所有事务页面(假设您坚持使用单一连接模型)。
从快速谷歌搜索来看,github 上似乎有几个 node-mysql 池。然而,在查看它们之后,它们看起来并不能帮助解决您的问题。