首页 > 解决方案 > mongodb中两个请求之间的竞争条件

问题描述

这是电子商务网站,我使用 mongodb 作为数据库,用户可以下订单,每个订单可以有多个产品。Product 是一个单独的表,其中包含每个产品的 quantityLeft。有一种情况,当两个并发请求来并尝试购买相同的产品时,orders 表中的订购商品超过了 product 表中的可用数量。

Product Table

{
  _id: '56e33c56ddec541556a61763',
  name: 'Chocolate',
  quantityLeft: 1
}

如果一次有一个请求,则在产品表中只剩下 1 块巧克力,它工作正常。请求来检查 order.quantity 并处理是否有足够的产品可用。

但是,当 2 个请求恰好同时出现时,请求查询数据库以获取产品并检查 quantityLeft 并发现只有 1 个巧克力可用,并通过检查库存中仍然存在足够数量并下订单。但实际上有 2 个订单,我们的数量只有 1 个。

Order Table

{
  _id: '60e33c56ddec541556a61595',
  items: [{
    _id: '56e33c56ddec541556a61763',
    quantity: 1
  }]
}

我尝试将这两个查询都放在同一事务中以获取产品详细信息并下订单,但它不起作用。像这样的东西

const session = await mongoose.startSession({ defaultTransactionOptions: { readConcern: { level: 'local' }, writeConcern: { w: 1 } } })

await session.withTransaction(async () => {
  const promiseArray = order.items.map((item) => Product.find({ _id: item._id }, { session })

  const products = Promise.all(promiseArray)
  
  const productById = {}
  products.forEach((product) => {
    productById[product._id] = product
  })

  order.items.forEach((item) => {
    if (productById[item].quantityLeft < order.item) {
      throw new Error('Not enough quantity')
    }
  })

  await Order.create(order, {session})

}, { readConcern: { level: 'local' }, writeConcern: { w: 1 } });

我正在使用nodejs(14.16),mongodb作为数据库npm包是mongoose(5.9)。

标签: node.jsmongodbmongoosetransactions

解决方案


推荐阅读