【问题标题】:Dangling transaction even though commit is called (node,Sequelize v5.21.9)悬空事务即使调用了提交(节点,Sequelize v5.21.9)
【发布时间】:2022-12-18 22:03:06
【问题描述】:

在使用 express 的节点应用程序中,我有一条使用下面显示的方法的路线。

我创建了一个 transaction 但不在 update 方法中使用它。 Sequelize配置为不是使用托管事务并将自动提交设置为 false。

当此路由被多次调用/每秒大约 7 - 10 次(调用次数不同)时,我最终得到 5 个左右的悬空事务,即使在方法调用结束时为事务调用了提交。(由于这些悬空事务,后续调用和我的节点应用程序无法再进行数据库调用)

如果我在 params 对象中传递 transaction,则不会发生此行为。而且我没有悬空交易。

发生这种情况的原因可能是什么?

    updateItem = (obj) => {
        this.logDebug(`Updating item - `, obj);

        return new Promise(async (resolve, reject) => {

            let transaction;
            try {
                transaction = await this.getTransaction();
            } catch(error) { return reject(error);


            const params = {
               where: {
                   id: obj.id
               },
               returning: true,
               plain: true
            };

            return models[modelName].
             update(obj, params).then(result => {
                   if (!result) { return result; }

                   result = JSON.parse(JSON.stringify(result[1]));
                   return result;
                }).
                then(async (result) => {
                    await transaction.commit();
                    return resolve(result);
                }).
                catch(async error => {
                    this.logError(`Failed to update - `, error);
                    await transaction.rollback();
                    return reject(error);
                });
        });
    };

导致悬空交易。


const params = {
   where: {
       id: obj.id
   },
   returning: true,
   plain: true
};

没有悬空交易发生。


const params = {
   where: {
       id: obj.id
   },
   returning: true,
   plain: true,
   transaction
};

使用Nodejs 12.4Sequelize 5.21.9postgres 9.x

仅在 params 对象中使用创建的 transaction 不会以某种方式导致悬空事务。
params 中不使用 transaction 会导致此悬空事务问题。

想知道这种行为的原因吗?这是我的代码的错误吗?或者Sequelize 的错误?

【问题讨论】:

  • 您可以使用 async/awaitthen/catch 但不能同时使用两者,这很混乱且容易出错。您能否将以return models[modelName]. 开头的代码转换为直接以await 开头的代码并尝试/捕获?

标签: node.js express transactions sequelize.js postgres-14


【解决方案1】:

这里有几点;

1-第一行末尾缺少一个花括号(我猜是一个简单的类型)
2-你不必使用第一个以外的回报
3-不需要在最后使用双“then”函数
4- 如果 json 解析失败你的交易可能泄漏

有了所有这些,代码可以像这样更新;

updateItem = (obj) => {
    this.logDebug(`Updating item - `, obj);

    return new Promise(async (resolve, reject) => {

        let transaction;
        try {
            transaction = await this.getTransaction();
        } catch (error) { return reject(error); }

        const params = {
            where: {
                id: obj.id
            },
            returning: true,
            plain: true
        };

        return models[modelName].
            update(obj, params).then(async (result) => {
                try {
                    resolve(JSON.parse(JSON.stringify(result[1])));
                    await transaction.commit();
                } catch (err) {
                    reject(err);
                }
            }).catch(async error => {
                this.logError(`Failed to update - `, error);
                await transaction.rollback(); // an extra try catch wont hurt here...
                reject(error);
            });
    });
};

但如果您想进行多次更新,事情可能会变得复杂。我可能会帮助您查看Multiple Transaction Manager's Sequelize context,以找到一种干净的方式来安排您的交易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 2013-06-28
    • 2023-03-30
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多