Scenes:
- Just apply on-line exclusion of large quantities request
- Deadlock found online multiple occurrences when trying to get lock error
Code:
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;
};
analysis:
- Error locations are being given at the time of this.app.model.Sku.destroy
- The reason Deadlock found when trying to get lock is inserted more things colleague updates the same table a piece of data
- In the case of small amount of data, the deadlock stands to reason that this should be very small but very high probability in fact occur
in conclusion:
- Should destroy notIn will involve the use of lock many rows, it resulted in a deadlock. But business destroy deleted data is usually 0. Destroy operation can be performed only when necessary.
- Update of time with little or no notIn operation
After optimizing the code:
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;
};