Nodejs中mysql事务处理,回滚没有反应

Nodejs中mysql事务处理,回滚没有反应

var config={
“host” : “localhost”,
“database” : “test”,
“user” : “root”,
“password” : “”

},mysql=require("mysql");

var connection = mysql.createConnection(config);

connection.beginTransaction(function(err) { if (err) { throw err; } connection.query(‘INSERT INTO UserInfo (NickName,InterestClassId,InterestId,Activity,Version,CreateTime) VALUES (?,?,?,?,?,?)’ ,[30, 17,18,1,1,new Date()] , function(err, result) { if (err) { connection.rollback(function() { throw err; }); } connection.query('INSERT INTO UserLoginInfo (UserId,LoginName,Password,CreateTime) VALUES (?,?,?,?) ,[17,18, 11,new Date()] , function(err, result) { if (err) { connection.rollback(function() { throw err; }); } connection.commit(function(err) { if (err) { connection.rollback(function() { throw err; }); } console.log(‘success!’); }); }); }); });

代码想实现的逻辑是先插入用户信息到UserInfo表,成功后在把用户名插入UserLoginInfo表。如果插入UserLoginInfo不成功则回滚将之前插入UserInfo表的数据删除。UserLoginInfo表的LoginName有唯一性约束,我在测试的时候故意提供了一个重名的LoginName,代码抛出UserLoginInfo插入错误后应该要回滚,将之前插入UserInfo的删除。可是我在数据库里查看之前插入UserInfo的记录还在。这两张表的存储结构都是InnoDB。请问问题出在什么地方?谢谢


5 回复

你遇到的问题可能是由于事务处理中的错误捕获和回滚机制没有正确执行导致的。在你的代码中,如果在插入 UserLoginInfo 表时发生错误,你应该通过调用 connection.rollback() 来回滚整个事务。但是,你的代码中有一些小错误,导致事务可能没有被正确回滚。

以下是修正后的代码:

var config = {
    "host": "localhost",
    "database": "test",
    "user": "root",
    "password": ""
};

var mysql = require("mysql");

var connection = mysql.createConnection(config);

connection.beginTransaction(function(err) {
    if (err) {
        throw err;
    }

    var insertUserInfoQuery = 'INSERT INTO UserInfo (NickName, InterestClassId, InterestId, Activity, Version, CreateTime) VALUES (?, ?, ?, ?, ?, ?)';
    var insertUserLoginInfoQuery = 'INSERT INTO UserLoginInfo (UserId, LoginName, Password, CreateTime) VALUES (?, ?, ?, ?)';

    connection.query(insertUserInfoQuery, [30, 17, 18, 1, 1, new Date()], function(err, result) {
        if (err) {
            connection.rollback(function() {
                console.error('Error occurred while inserting UserInfo:', err);
                throw err;
            });
        } else {
            connection.query(insertUserLoginInfoQuery, [17, 18, 11, new Date()], function(err, result) {
                if (err) {
                    connection.rollback(function() {
                        console.error('Error occurred while inserting UserLoginInfo:', err);
                        throw err;
                    });
                } else {
                    connection.commit(function(err) {
                        if (err) {
                            connection.rollback(function() {
                                console.error('Error occurred while committing transaction:', err);
                                throw err;
                            });
                        } else {
                            console.log('Transaction completed successfully!');
                        }
                    });
                }
            });
        }
    });
});

解释

  1. 事务初始化

    • 使用 connection.beginTransaction() 开始一个事务。
  2. 插入 UserInfo

    • 如果插入 UserInfo 表失败,则调用 connection.rollback() 回滚事务,并抛出错误。
  3. 插入 UserLoginInfo

    • 在插入 UserLoginInfo 表之前,检查是否有错误发生。如果有错误,则调用 connection.rollback() 回滚事务,并抛出错误。
  4. 提交事务

    • 如果两个插入操作都成功,则调用 connection.commit() 提交事务。如果提交过程中出现错误,则再次调用 connection.rollback() 回滚事务,并抛出错误。

通过这种方式,你可以确保在任何一步失败时都能正确回滚事务,从而保证数据的一致性。


1:应该是可以的啊
2:你这样直接使用,事务代码和业务逻辑代码紧密耦合在一起,建议使用 bearcat-dao 来处理事务哈

1:可是之前插入UserInfo表的数据,无论之后插入UserLoginInfo表是否成功都一直存在,不会回滚,是不是mysql配置方面有问题呢?还是开发环境的问题,我是用的mac,被这个问题搞死了,要疯了~~~~ 2: bearcat-dao没使用过,我研究下,谢谢提醒

问题解决了,还是表的存储结构的问题,之前用phpmyadmin改过表的存储结构。以为改成InnoDB了,没想到phpMyAdmin没有改成功,谢谢fantasyni的回复,让我坚定了代码没有问题的判断,又查了一遍数据库设置。以后还是用命令行修改数据库靠谱!

你遇到的问题是因为在事务处理中,每个 connection.query 调用都需要在回调函数中进行错误处理,并且需要确保在所有操作完成后正确地提交或回滚事务。

在你的代码中,存在一些语法错误和逻辑问题,导致事务无法正常工作。具体来说:

  1. 每个 connection.query 都需要检查错误并调用相应的回滚操作。
  2. 你需要确保在所有查询完成后才进行提交操作。

以下是修正后的示例代码:

var config = {
    "host": "localhost",
    "database": "test",
    "user": "root",
    "password": ""
};

var mysql = require("mysql");
var connection = mysql.createConnection(config);

connection.beginTransaction(function (err) {
    if (err) { 
        throw err; 
    }

    var insertUserInfoQuery = 'INSERT INTO UserInfo (NickName, InterestClassId, InterestId, Activity, Version, CreateTime) VALUES (?, ?, ?, ?, ?, ?)';
    var insertUserLoginInfoQuery = 'INSERT INTO UserLoginInfo (UserId, LoginName, Password, CreateTime) VALUES (?, ?, ?, ?)';

    // 插入 UserInfo 表
    connection.query(insertUserInfoQuery, [30, 17, 18, 1, 1, new Date()], function (err, userInfoResult) {
        if (err) {
            connection.rollback(function () {
                console.error('UserInfo 插入失败,事务已回滚');
                throw err;
            });
        } else {
            // 插入 UserLoginInfo 表
            connection.query(insertUserLoginInfoQuery, [17, 18, 11, new Date()], function (err, userLoginInfoResult) {
                if (err) {
                    connection.rollback(function () {
                        console.error('UserLoginInfo 插入失败,事务已回滚');
                        throw err;
                    });
                } else {
                    // 提交事务
                    connection.commit(function (err) {
                        if (err) {
                            connection.rollback(function () {
                                console.error('事务提交失败,事务已回滚');
                                throw err;
                            });
                        } else {
                            console.log('success!');
                        }
                    });
                }
            });
        }
    });
});

解释

  1. 事务开始:使用 beginTransaction 开始一个事务。
  2. 插入 UserInfo 表:执行插入 UserInfo 的 SQL 语句。
    • 如果发生错误,则立即调用 rollback 方法回滚事务。
  3. 插入 UserLoginInfo 表:执行插入 UserLoginInfo 的 SQL 语句。
    • 如果发生错误,则立即调用 rollback 方法回滚事务。
  4. 提交事务:如果两个插入都成功,则调用 commit 方法提交事务。

通过这种方式,你可以确保在任何一步操作失败时,事务会被正确回滚,从而保证数据的一致性。

回到顶部