系统城装机大师 - 固镇县祥瑞电脑科技销售部宣传站!

当前位置:首页 > 数据库 > MsSql > 详细页面

数据库死锁的问题,Deadlock found when trying to get lock; try restarting transaction at Query.formatError

时间:2019-12-02来源:电脑系统城作者:电脑系统城

  • 场景:

    • 应用刚上线排除大批量请求的问题
    • 线上多次出现的Deadlock found when trying to get lock错误

  • 代码:

async batchUpdate(skus, { transaction }) {
    const result = await Promise.all(skus.map(async sku => {
      const record = await this.app.model.Sku.upsert(sku, { transaction });
      return record;
    }));

    // SaaS 中删掉的 sku,插件也要同步删除
    const ids = _.map(skus, 'sku_id');
    const productIds = _.map(skus, 'product_id');
    const { Op } = this.app.Sequelize;
    
    await this.app.model.Sku.destroy({
      where: {
        sku_id: { [Op.notIn]: ids },
        product_id: productIds,
      }, transaction,
    });

    return result;
  };
  • 分析:

    • 报错位置都是在this.app.model.Sku.destroy的时候报错
    • Deadlock found when trying to get lock的原因是多个事物同事更新插入同一表的某一段数据
    • 在数据量不大的情况下,按道理说发生这种死锁的情况应该非常少但是事实上出现的概率很高
  • 结论:

    • 应该是destroy使用notIn会涉及到很多行的锁定,所以造成了死锁。但是业务上destroy删除的数据一般为0条。所以可以只在必要的时候进行destroy操作。
    • 更新的时候少用或不用notIn操作
  • 优化后代码:

  async batchUpdate(skus, { transaction }) {
    const result = await Promise.all(skus.map(async sku => {
      const record = await this.app.model.Sku.upsert(sku, { transaction });
      return record;
    }));

    // SaaS 中删掉的 sku,插件也要同步删除
    const ids = _.map(skus, 'sku_id');
    const productIds = _.map(skus, 'product_id');
    const { Op } = this.app.Sequelize;
    const delSkus = await this.app.model.Sku.findAll({
      where: {
        sku_id: { [Op.notIn]: ids },
        product_id: productIds,
      }, transaction,
    });
    if (delSkus && delSkus.length) {
      await this.app.model.Sku.destroy({
        where: {
          sku_id: delSkus.map(sku => sku.sku_id),
        }, transaction,
      });
    }

    return result;
  };
  • 参考:
    • https://www.cnblogs.com/rainy-shurun/p/5166163.html
    • https://www.jianshu.com/p/6049b046e7b4
分享到:

相关信息

系统教程栏目

栏目热门教程

人气教程排行

站长推荐

热门系统下载