Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js+MySQL-处理事务_Javascript_Mysql_Database_Transactions_Node.js - Fatal编程技术网

Javascript Node.js+MySQL-处理事务

Javascript Node.js+MySQL-处理事务,javascript,mysql,database,transactions,node.js,Javascript,Mysql,Database,Transactions,Node.js,我正在使用express和node mysql驱动程序在node.js上构建一个应用程序。在我的应用程序中,有几种情况下我需要进行一系列数据库插入/更新。我希望在事务中使用它们,这样,如果第二个或第三个插入失败,那么之前的插入将完全回滚 目前,我这样做的方式是使用某种中间件,在请求到达时启动事务。在处理请求的过程中,如果抛出任何错误,我将捕获该错误并进行回滚。如果没有发生错误,我会在将响应发送到浏览器之前进行提交 然而,我现在担心的是,当多个用户同时访问应用程序时,这将不起作用,因为如果另一个请

我正在使用express和node mysql驱动程序在node.js上构建一个应用程序。在我的应用程序中,有几种情况下我需要进行一系列数据库插入/更新。我希望在事务中使用它们,这样,如果第二个或第三个插入失败,那么之前的插入将完全回滚

目前,我这样做的方式是使用某种中间件,在请求到达时启动事务。在处理请求的过程中,如果抛出任何错误,我将捕获该错误并进行回滚。如果没有发生错误,我会在将响应发送到浏览器之前进行提交

然而,我现在担心的是,当多个用户同时访问应用程序时,这将不起作用,因为如果另一个请求试图用START transaction开始自己的事务,MySQL将执行强制提交!我目前只使用一个节点实例,所有请求都使用一个MySQL连接


有人能告诉我我的担忧是否有效,以及我应该如何获得事务支持吗?

我发现很难相信,如果一个单独的会话执行一个启动事务,其他事务就会提交。这将是完全不安全的,尤其是当数据需要回滚或是回滚时

您是否可能将其与同一个会话启动事务混为一谈? 请参阅其中解释了不能嵌套事务的地方。这当然适用于同一个会话,而不是另一个用户的会话

假设您没有弄乱会话的隔离级别或全局隔离级别,那么事务应该是安全的


在任何情况下,如果您想对事务进行排队,那么在节点中构建一个全局队列对象并链接调用并不困难,以便一个调用在另一个调用完成时启动。一个带有push和pop的简单数组应该可以做到这一点。

您需要创建一个客户机池,或者以某种方式确保两个不同的页面不会在同一个连接上插入命令,至少当它们中的任何一个在事务中时

由于您希望根据前面命令的结果有条件地执行回滚,因此需要通过db调用的回调将它们链接在一起,而不依赖于节点mysql队列行为。这将打开一个窗口,让其他页面进入,并按照您的建议在同一连接上排队执行操作

您可以创建和管理自己的队列,但如果您坚持使用单连接模型,那么最终会序列化所有事务性页面

通过快速的谷歌搜索,github上似乎有几个节点mysql池。但是,在看了它们之后,它们看起来不会帮助解决您的问题。

请查看

我为节点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 ;
您的节点代码如下所示:

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 ...

    }
});

只是一个想法:在postresql上,您可以启动一个事务并为其设置一个ID。因此,您可以重用相同的连接,因为如果您需要提交或回滚,您将通过id引用您的事务,对吗?

如果您有选择,那么可能值得使用coach/redis/mongo,因为node更容易使用。如果您已经有MYSQL数据库,请继续使用该数据库。@Raynos AFAIK MongoDb不支持事务……在MYSQL上下文中,一个连接等于一个“会话”。OP使用一个连接,所以它是一个MySQL会话,在所有请求处理中共享。@SystemParadox,没错。我理解这个问题是一个单独连接的问题,当OP说单个连接是指每个用户时。这实际上是一个非常有趣的方法来解决这个问题-我在想,可能在服务器启动时预处理查询,并将对ORM的调用转换为存储过程?如果你能给我一张纸条,我很想听听你对最好的工作方式的想法。我正在研究一个叫做水线的交叉数据库ORM。