node.js中Sequelize的事务失败回滚日志正常,但是数据库还是插入记录了

其实事务这块都没问题,model里面封装的问题,现在已经解决了。谢谢各位回复

官方手动提交事务的结果,效果并没有改变,很多写法都尝试了一边,最后都是第一条记录插入成功,没有回滚和日志不一样
image.png

日志看到有回滚动作,但是数据库还有插入第一条数据
image.png

修改异步的写法,结果一样,如数据库成功插入数据companys,

image.png

阅读 3.8k
1 个回答

看你的图,其实你的 CompanyModel.createthat.baseCreate 都没有加入到事务里面,看你的 start transactionrollback 前都有一个id

这个是Sequelize用来标识事务的,这个id相同说明在同一个事务,如果你的两个sql也是这个事务的,Executing 后跟的就不是 (default) 了,而是这个id

你的用法不对。参考文档示例:

        /**
         * Start a transaction. When using transactions, you should pass the transaction in the options argument
         * in order for the query to happen under that transaction
         *
         * ```js
         * sequelize.transaction().then(function (t) {
         *   return User.find(..., { transaction: t}).then(function (user) {
         *     return user.updateAttributes(..., { transaction: t});
         *   })
         *   .then(t.commit.bind(t))
         *   .catch(t.rollback.bind(t));
         * })
         * ```
         *
         * A syntax for automatically committing or rolling back based on the promise chain resolution is also
         * supported:
         *
         * ```js
         * sequelize.transaction(function (t) { // Note that we use a callback rather than a promise.then()
         *   return User.find(..., { transaction: t}).then(function (user) {
         *     return user.updateAttributes(..., { transaction: t});
         *   });
         * }).then(function () {
         *   // Commited
         * }).catch(function (err) {
         *   // Rolled back
         *   console.error(err);
         * });
         * ```
         *
         * If you have [CLS](https://github.com/othiym23/node-continuation-local-storage) enabled, the transaction
         * will automatically be passed to any query that runs witin the callback. To enable CLS, add it do your
         * project, create a namespace and set it on the sequelize constructor:
         *
         * ```js
         * var cls = require('continuation-local-storage'),
         *     ns = cls.createNamespace('....');
         * var Sequelize = require('sequelize');
         * Sequelize.cls = ns;
         * ```
         * Note, that CLS is enabled for all sequelize instances, and all instances will share the same namespace
         *
         * @param options Transaction Options
         * @param autoCallback Callback for the transaction
         */
        transaction<T>(options: TransactionOptions,
            autoCallback: (t: Transaction) => PromiseLike<T>): Promise<T>;
        transaction<T>(autoCallback: (t: Transaction) => PromiseLike<T>): Promise<T>;
        transaction(options?: TransactionOptions): Promise<Transaction>;

第二个图的代码改写

async insertTest(){
    let that = this;
    return await db.transaction(async(t)=>{

        // ...
        await that.baseCreate(person , {transaction : t});
        // 这行代码加多一个 return  改成下面的试试

        return await that.baseCreate(person , {transaction : t});
    })
}

上面的写法,如果还是不行的话,说明 CompanyModel.create() 得写成 你的第一幅图的形式,在你第一幅图的这两行代码前:

await CompanyModel.create() 改成 return await CompanyModel.create()

await that.baseCreate()   改成 return await that.baseCreate()

各加一个return  

这个是参考官方文档的写法,其实这种方法写起来很繁琐,推荐下面的写法,不过得手动提交和回滚事务

async insertTest(){

    let t = await db.transaction();
    try {

        await CompanyModel.create(company , {transaction : t});
        await this.baseCreate(person , {transaction : t});
        await t.commit()// 提交事务
    } catch (error) {
        console.log(error);
        await t.rollback()
    }
}

直接可以使用this , 也不必再写最外层 thencatch 了,只要你的同一个事务的id是一样的,说明没问题了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题