【问题标题】:Multiple Transactions in mysql for Nodemysql for Node 中的多个事务
【发布时间】:2021-12-07 00:16:45
【问题描述】:

我正在使用 node 的 mysql 驱动程序,需要一个接一个地执行“n”个事务,而不是同时执行。

我尝试使用 for/forEach 循环,但事务似乎同时发生,这导致我的 api 崩溃。这是错误:-

throw err; // Rethrow non-MySQL errors
      ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

一个单一的交易似乎工作得很好。

每个事务有4个查询,req.body是一个对象数组:-

router.post('/production/add', (req, res) => {
    for (const obj of req.body) {
        pool.getConnection(function (err, connection) {
            connection.beginTransaction(function (err) {
                if (err) throw err;

                const query1 = `select qty from production where prc_id = ${obj.prc_id}`;
                console.log(query1);
                connection.query(query1, function (error, result1, fields) {
                    if (error) {
                        return connection.rollback(function () {
                            res.status(400).send({ query: 1, message: error.sqlMessage, code: error.code, errno: error.errno });
                            return;
                        });
                    }
                    const new_prod_qty = result1[0].qty - obj.auth_prod_qty;
                    const query2 = new_prod_qty > 0 ? `update production set qty = ${new_prod_qty} where prc_id = ${obj.prc_id}` : `delete from production where prc_id = ${obj.prc_id}`;
                    console.log(query2);
                    connection.query(query2, function (error, results2, fields) {
                        if (error) {
                            return connection.rollback(function () {
                                res.status(400).send({ message: error.sqlMessage, code: error.code, errno: error.errno });
                                return;
                            });
                        }
                        const query3 = `update prc set auth_prod_qty = ${obj.auth_prod_qty} where prc_id = ${obj.prc_id}`;
                        console.log(query3);
                        connection.query(query3, function (error, results3, fields) {
                            if (error) {
                                return connection.rollback(function () {
                                    res.status(400).send({ message: error.sqlMessage, code: error.code, errno: error.errno });
                                    return;
                                });
                            }
                            const query4 = "select * from store";
                            connection.query(query4, function (error, results3, fields) {
                                if (error) {
                                    return connection.rollback(function () {
                                        res.status(400).send({ message: error.sqlMessage, code: error.code, errno: error.errno });
                                        return;
                                    });
                                }
                                connection.commit(function (err) {
                                    if (err) {
                                        return connection.rollback(function () {
                                            res.status(400).send({ message: error.sqlMessage, code: error.code, errno: error.errno });
                                            return;
                                        });
                                    }
                                    res.status(201).send(results2);
                                });
                            });
                        });
                    });
                });
            });
        });
    };
});

根据一些研究,Sequelize ORM 似乎可以促进交易,但我希望将其用作最后的手段。任何有或没有 Sequelize 的解决方案都将不胜感激!

提前致谢!

【问题讨论】:

  • 欢迎来到 StackOverflow。通常最好回答您自己的问题,而不是在找到答案后更新您的问题。

标签: mysql node.js express transactions sequelize.js


【解决方案1】:

您需要使用async / await 按顺序运行您的交易。如何做到这一点?

使用npm mysql2 代替npm mysql。当您 require('mysql2/promise') 时,您可以获得 promisified (awaitable) versions 的 API。另外,与那些可悲的嵌套回调相比,这更多在编程和调试方面更有趣。只是不要忘记awaits。

将此基本大纲用于代码的数据处理循环。一切都会按顺序进行。创建游泳池的方式有点不同;阅读 npm 页面。这是未调试的。

const mysql = require('mysql2/promise');

router.post('/production/add', async (req, res) => {
  const connection = await pool.getConnection()

  for (const obj of req.body) {
    try {
      await connection.beginTransaction()
      const query1 = 'whatever'
      const result1 = await connection.query(query1)
      const query2 = 'something else'
      const result 2 = await connection.query(query2)
      /* etcetera etcetera */
      await connection.commit()
    } 
    catch (error) {
      await connection.rollback()
      pool.releaseConnection()
      res.status(400).send({ something })
    }
  }
  pool.releaseConnection()
}

【讨论】:

  • 很好的建议,这正是我一直在寻找的,因为它也适用于 mysql,并且只使用 promise() 方法将 mysql 连接升级到 mysql2 连接的承诺版本!我已经编辑了问题以包括我的实施任何批评?
【解决方案2】:

mysql2/promise 正是我正在寻找的包,它与 mysql 一起使用并使用 promise() 方法将 mysql 连接升级为基于 promise 的 mysql2 连接。

router.post('/stock/add', async (req, res) => {
    const connection = pool.getConnection(async function (err, connection) {
        if (err) {
            connection.release();
            res.status(400).send(err);
            return;
        }
        else {
            for (const obj of req.body) {
                try {
                    await connection.promise().beginTransaction();
                    const [result1, fields1] = await connection.promise().query(query1)
                    const [result2, fields2] = await connection.promise().query(query2);
                    const [result3, fields3] = await connection.promise().query(query3);
                    const [result4, fields4] = await connection.promise().query(query4);
                    await connection.promise().commit();
                }
                catch (error) {
                    await connection.promise().rollback();
                    connection.release();
                    res.status(400).send(error);
                    return;
                }
            }
            res.status(200).send('Transaction Complete');
        }
    });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 2017-07-18
    相关资源
    最近更新 更多