简体   繁体   English

Nodejs mysql 事务回滚不起作用

[英]Nodejs mysql transaction rollback not working

I am using Nodejs MySQL and tried to create database level transaction so that I can execute a bunch of statements in a batch and rollback if there is an error in any step.我正在使用 Nodejs MySQL 并尝试创建数据库级事务,以便我可以批量执行一堆语句并在任何步骤出现错误时回滚。 I tried to follow this tutorial.我尝试按照教程进行操作。

My database module is:我的数据库模块是:

let mysql = require('mysql')
let keys = require('../config/keys')
let util = require('util')

let pool = mysql.createPool({
    connectionLimit: 20,
    host: keys.connection.host,
    user: keys.connection.user,
    password: keys.connection.password,
    database: keys.connection.database,
    dateStrings: true
    // debug:true                //Set this to true for verbose debugging. Leaving this to default for now cause it is creating too many messages at my console
})
pool.getConnection((err, connection) => {
    if (err) {
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            console.error('Database connection was closed.')
        }
        if (err.code === 'ER_CON_COUNT_ERROR') {
            console.error('Database has too many connections.')
        }
        if (err.code === 'ECONNREFUSED') {
            console.error('Database connection was refused.')
        }
    }
    if (connection) connection.release()
    return
})

pool.query = util.promisify(pool.query)

const connection = () => {
    return new Promise((resolve, reject) => {
        pool.getConnection((err, connection) => {
            if (err) reject(err);

            console.log("MySQL pool connected: threadId " + connection.threadId);

            const query = (sql, binding) => {
                return new Promise((resolve, reject) => {
                    connection.query(sql, binding, (err, result) => {
                        if (err) reject(err);
                        resolve(result);
                    });
                });
            };

            const release = () => {
                return new Promise((resolve, reject) => {
                    if (err) reject(err);
                    console.log("MySQL pool released: threadId " + connection.threadId);
                    resolve(connection.release());
                });
            };
            resolve({
                query,
                release
            });
        });
    });
};
// const query = (sql, binding) => {
//  return new Promise((resolve, reject) => {
//      pool.query(sql, binding, (err, result, fields) => {
//          if (err) reject(err);
//          resolve(result);
//      });
//  });
// };
module.exports = {
    pool,
    connection
}

In my route, I am trying to use the connection which should allow transaction:在我的路线中,我正在尝试使用应该允许交易的连接:

const mysql = require('../../middleware/database')

async function buildCoreSchemas(){
      const connection = await mysql.connection();
    
    try{

        await connection.query("START TRANSACTION");

         await connection.query(`CREATE TABLE adjustreason (
            AdjustID int NOT NULL AUTO_INCREMENT,
            AdjustReason varchar(100) NOT NULL,
            PRIMARY KEY (AdjustID)
          )`)
      
        await connection.query(`insert into adjustreason(AdjustReason) values('sdsds')`) 
        
        await connection.query(`insert into adjustreason(FAKECOLUMN) values('sdsds')`)  
        await connection.query("COMMIT");
        }
    catch(err){
        await connection.query("ROLLBACK");
        console.log(err)
        return false
    }
    finally {
    await connection.release();
  }

As you can see I my second insert statement is wrong as there is no column name called FAKE COLUMN .如您所见,我的第二个插入语句是错误的,因为没有名为FAKE COLUMN的列名。 So, the error gets caught and I get the error message in my console:因此,错误被捕获,我在控制台中收到错误消息:

Unknown column 'FAKECOLUMN' in 'field list '字段列表中的未知列'FAKECOLUMN'

But when I go and look at my database the transaction is not rollbacked because I can see that the first record is still there.但是当我 go 并查看我的数据库时,事务没有回滚,因为我可以看到第一条记录仍然存在。 What am I doing wrong?我究竟做错了什么?

Ciao, try to modify code in this way: Ciao,尝试这样修改代码:

connection.beginTransaction(function(err) {
 if (err) { throw err; }
   connection.query(`CREATE TABLE adjustreason (
        AdjustID int NOT NULL AUTO_INCREMENT,
        AdjustReason varchar(100) NOT NULL,
        PRIMARY KEY (AdjustID)
      )`, function (error, results, fields) {
 if (error) {
  return connection.rollback(function() {
    throw error;
  });
 }

connection.query(`insert into adjustreason(AdjustReason) values('sdsds')`, function 
(error, results, fields) {
  if (error) {
    return connection.rollback(function() {
      throw error;
    });
  }

 connection.query(`insert into adjustreason(FAKECOLUMN) values('sdsds')`, function 
 (error, results, fields) {
  if (error) {
    return connection.rollback(function() {
      throw error;
    });
  }
  connection.commit(function(err) {
    if (err) {
      return connection.rollback(function() {
        throw err;
      });
    }
    console.log('success!');
  });
});
});
});
});

so you call connection.query inside connection.beginTransaction and if one of those query fails, you call connection.rollback.所以你在connection.beginTransaction中调用connection.query,如果其中一个查询失败,你调用connection.rollback。 Otherwise connection.commit否则connection.commit

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM