请问Nodejs的mysql模块为什么无法回滚?

请问Nodejs的mysql模块为什么无法回滚?

按照github中mysql模块的wiki来的,不可用啊。mysql已经设置innodb autocommit也关闭了,代码贴下来,麻烦大家帮忙看看。 connection.beginTransaction(function (err) { if (err) { throw err; res.json({ success : false, err : err }); return ; }

			var delete_sql = "delete from tp_lbs where type= ?";
			// var delete_sql = 'insert into tp_lbs (name, address, phone, longitude, latitude, type) values (1,2,3,4,5,6)';
			connection.query(delete_sql, [type], function (err, result) {
				if(err) {
					connection.rollback(function() {
				        throw err;
				    });
				    res.json({
						success : false,
						err : err
					});
					return ;
				}
				var sql = "sekect  name from tp_lbs where ,.";
				connection.query(sql, [], function (err, result) {
					if(err) {
						connection.rollback(function() {
					        throw err;
					    });
					    res.json({
							success : false,
							err : err
						});
						return ;
					}
					connection.commit(function(err) {
			        if (err) { 
			          connection.rollback(function() {
			            throw err;
			            res.json({
							success : false,
							err : err
						});
						return ;
			          });
			        }
			        res.json({
						success : false,
						err : err
					});
				});
			});

		});
		
	});

2 回复

问题描述

在使用 Node.js 的 mysql 模块进行数据库操作时,你遇到了一个问题:在执行事务过程中,即使遇到错误也无法成功回滚。具体来说,你在尝试删除记录后,想要通过回滚来撤销已执行的操作,但发现事务并没有按预期回滚。

原因分析

主要问题出在以下几点:

  1. SQL 错误处理:在查询 SQL 语句时,你使用了错误的表名或列名(如 sekect 而不是 select),这会导致查询失败,但在捕获到错误后没有正确处理回滚逻辑。
  2. 事务提交与回滚逻辑:你的代码中,在提交事务时,如果发生错误会触发回滚,但你没有正确处理回滚后的逻辑,导致回滚操作可能被忽略。

示例代码及修正

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

const mysql = require('mysql');

// 创建连接
const connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'testdb'
});

connection.connect((err) => {
    if (err) {
        console.error('Error connecting to database:', err.stack);
        return;
    }
    console.log('Connected as id ' + connection.threadId);
});

// 开始事务
connection.beginTransaction(function (err) {
    if (err) {
        throw err;
    }

    const type = 1; // 假设 type 是你要删除的类型
    const delete_sql = "DELETE FROM tp_lbs WHERE type = ?";

    connection.query(delete_sql, [type], function (err, result) {
        if (err) {
            console.error("Delete query failed:", err);
            connection.rollback(function () {
                console.error("Rollback executed");
            });
            res.json({
                success: false,
                err: err
            });
            return;
        }

        const select_sql = "SELECT name FROM tp_lbs WHERE type = ?";
        connection.query(select_sql, [type], function (err, result) {
            if (err) {
                console.error("Select query failed:", err);
                connection.rollback(function () {
                    console.error("Rollback executed");
                });
                res.json({
                    success: false,
                    err: err
                });
                return;
            }

            connection.commit(function (err) {
                if (err) {
                    console.error("Commit failed, rolling back:", err);
                    connection.rollback(function () {
                        console.error("Rollback executed");
                    });
                    res.json({
                        success: false,
                        err: err
                    });
                    return;
                }

                console.log("Transaction committed successfully");
                res.json({
                    success: true,
                    data: result
                });
            });
        });
    });
});

关键点解释

  1. 事务开始:使用 beginTransaction() 方法开启事务。
  2. 错误处理:在每个查询后检查是否有错误,如果有则调用 rollback() 方法进行回滚,并返回错误信息。
  3. 事务提交:在所有查询都成功后,使用 commit() 方法提交事务。如果提交过程中出现错误,则再次调用 rollback() 方法进行回滚。

通过以上修改,你可以确保在事务过程中正确地处理错误并执行回滚操作。


根据你提供的代码片段,你的MySQL事务确实存在一些问题。主要问题包括SQL语法错误(例如sekect应该是select)以及一些逻辑上的不足。下面是修复后的示例代码,以及如何正确使用事务回滚的方法。

示例代码

const mysql = require('mysql');
const connection = mysql.createConnection({
    host: 'localhost',
    user: 'yourusername',
    password: 'yourpassword',
    database: 'yourdatabase'
});

connection.connect();

connection.beginTransaction(function (err) {
    if (err) {
        return handleError(res, err);
    }

    const delete_sql = "DELETE FROM tp_lbs WHERE type=?";
    connection.query(delete_sql, [type], function (err, result) {
        if (err) {
            return handleRollback(connection, res, err);
        }

        const select_sql = "SELECT name FROM tp_lbs WHERE type=?";
        connection.query(select_sql, [type], function (err, result) {
            if (err) {
                return handleRollback(connection, res, err);
            }

            connection.commit(function (err) {
                if (err) {
                    return handleRollback(connection, res, err);
                }
                res.json({
                    success: true,
                    data: result
                });
            });
        });
    });
});

function handleRollback(connection, res, err) {
    connection.rollback(function () {
        res.json({
            success: false,
            err: err
        });
    });
}

function handleError(res, err) {
    console.error("Transaction error:", err);
    res.json({
        success: false,
        err: err
    });
}

关键点解释

  1. 连接初始化:确保连接正确初始化并能正常工作。
  2. 事务开始:使用beginTransaction开始一个事务。
  3. 查询与回滚
    • 每次执行查询后检查是否有错误。如果有,则调用handleRollback函数来执行回滚操作。
    • handleRollback函数中,使用rollback方法撤销事务中的所有更改,并返回错误信息给客户端。
  4. 提交事务:如果所有查询都成功执行,则调用commit方法完成事务。

通过这种方式,可以确保在出现任何错误时,事务会被正确地回滚,从而保持数据库的一致性。

回到顶部