mysql - Sequelize : Using truncate and insert within same transaction

标签 mysql node.js sequelize.js

我需要截断我的一个表,然后在它之后,我需要通过bulkCreate 使用新的dataCollection 重新填充它。所有这些都应该在一个事务中进行,我希望它能够简单地工作,但我无法让它工作,任何建议我如何使用 truncate 然后使用 bulkCreate单个事务中的模型?

这是我的代码片段

try {
                promises.push(
                    models.sequelize.transaction(function (t) {
                        return infx.destroy({
                            where: {},
                            truncate: true,
                            transaction: t
                        }).then(function () {
                            return infx.bulkCreate(dataCollection, {
                                transaction: t
                            });
                        });
                    }).then(function (result) {
                        // Transaction has been committed
                    }).catch(function (err) {
                        sendEmailOnError(err, 0, 0)
                        logger.error(err);
                    })
                );
            } catch (error) {
                console.log("Input On End error", error);
                logger.error(error);

            }
            return Promise.all(promises).then(() => {
                    doMoreThings().then(someData => {                                                        
                        console.log('Import complete! Shutting down process now.');
                        process.exit(0);
                    })
                })
                .catch((e) => {
                    // console.log("error", e);
                    logger.error(e);
                });

再次尝试使用 async...await,事务仍然不会回滚截断的数据。

Un-managed transaction

        let t;
        try {
            t = await models.sequelize.transaction();

            //truncate table
            await infx.destroy({
                where: {},
                truncate: true,
                transaction: t
            });

            //insert new bulk collection
            await infx.bulkCreate(dataCollection, {
                transaction: t
            });

            // commit
            await t.commit();
        } catch (error) {
            // console.log("Input On End error", error);
            if (error) await t.rollback();
            sendEmailOnError(error, 0, 0);
            // logger.error(error);

        }

Managed Transaction

try {
                result = await models.sequelize.transaction(
                    async (t) => {
                        //truncate table
                        await infx.destroy({
                            where: {},
                            truncate: true,
                            transaction: t
                        });

                        //insert new bulk collection
                        return await infx.bulkCreate(dataCollection, {
                            transaction: t
                        });
                    });
            } catch (error) {
                console.log("Input On End error", error);
                sendEmailOnError(error, 0, 0);
                // logger.error(error);
            }

Sequelize log (everything is well executed within transaction)

Executing (8f53bd47-e324-48b7-8c7d-ea93dcbdae5c): START TRANSACTION;
Executing (8f53bd47-e324-48b7-8c7d-ea93dcbdae5c): TRUNCATE `infxes`
Executing (8f53bd47-e324-48b7-8c7d-ea93dcbdae5c): INSERT INTO `infxes` (...);
Executing (8f53bd47-e324-48b7-8c7d-ea93dcbdae5c): ROLLBACK;

最佳答案

显然这与:

Although TRUNCATE TABLE is similar to DELETE, it is classified as a DDL statement rather than a DML statement.

  • Truncate operations cause an implicit commit, and so cannot be rolled back.

引用文献:

https://dev.mysql.com/doc/refman/8.0/en/truncate-table.html

https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html

对于我的场景,我可以选择使用删除而不是截断:

           result = await models.sequelize.transaction(
                async (t) => {
                    //truncate table
                    await infx.destroy({
                        where: {},
                        transaction: t
                    });                     

                    //insert new bulk collection
                    return await infx.bulkCreate(dataCollection, {
                        transaction: t
                    });
                });
        } catch (error) {
            logger.error(error);
        }

关于mysql - Sequelize : Using truncate and insert within same transaction,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57366716/

相关文章:

python - 迁移到 mysql-django-uwsgi-nginx 期间出现内部服务器错误

javascript - 为什么 Node.js(文件名)会导致 Windows 上的 Node.JS 出现问题?

javascript - Sequelize - 如何按顺序执行查询?

sequelize.js - 在哪里使用 Sequelize JS 和 MySQL

javascript - 更新时调用了两次 Sequelize afterValidate 钩子(Hook)

mysql - SQL Server 到 MySql 的转换 - 模式与数据库问题

mysql - docker-compose up invalid mode/docker-entrypoint-initdb.d/- 无法为服务数据库创建容器

node.js - 无法使用 google-cloud node.js 客户端插入 BigQuery

javascript - Nodejs 上的 xml 到 json 错误 : TypeError: Cannot read property 'toString' of null

php - 如何在 PHP 和 MySQL 中建立一个多类别的管理员?