dcloud云函数中如何使用事务

本文通过示例介绍了如何在高并发场景下使用云函数和数据库事务来防止超卖问题。通过事务确保库存减少操作的原子性,如果更新失败则回滚事务,保证数据一致性。同时,注意到不同云服务商对于事务操作的限制,例如阿里云不支持where方法进行多条修改。示例中展示了两个账户转账的事务处理过程,强调了transaction.doc().get()返回结果不是数组形式的重要细节。
摘要由CSDN通过智能技术生成

官方文档:https://uniapp.dcloud.io/uniCloud/cf-database?id=transaction

事务通常用来在某个数据库操作失败之后进行回滚。

案例1:高并发下简单的防止超卖
高并发时很多用户同时对一条数据读写,很容易造成数据混乱,表现在秒杀抢购等场景就是超卖。以秒杀为例,开发者可以从扣除库存这步入手对超卖进行很大程度的限制,下面是一个简单的示例:

// 云函数
const db = uniCloud.database()
const dbCmd = db.command
exports.main = async function(event){
  const transaction = await db.startTransaction()
  // 其他业务逻辑...
  // 库存减一
  // 这里要注意,操作数据库的时候是使用transaction.collection,而不是往常的写法db.collection
  const reduceRes = await transaction.collection('goods').doc('goods_id').update({
    stock: dbCmd.inc(-1)
  })
  if(reduceRes.updated === 0) { // 如果没成功更新库存就认为下单失败
    await transaction.rollback()
    return {
      code: 1001,
      message: '下单失败'
    }
  }else {
        await transaction.commit()
        console.log(`transaction succeeded`)

        return {
          success: true,
          message: '下单成功'
        }
      }
}

限制

事务操作时为保障效率和并发性,只允许进行单记录操作,不允许进行批量操作,但可以在一个事务进行多次数据库操作。

  • 以前阿里云对于修改和删除仅支持使用doc方法,不支持使用where方法(现在不知道如何,有待测试)。
  • 新增时使用add方法一次只可以新增单条,不可新增多条,即不支持在add方法内传入数组
  • 腾讯云没有限制where的使用,但是使用where修改或删除多条会导致无法回滚

注意事项

  • 请注意transaction.doc().get()返回的data不是数组形式

示例代码

两个账户之间进行转账的简易示例(阿里云):

const db = uniCloud.database()
const dbCmd = db.command

exports.main = async (event) => {
  const transaction = await db.startTransaction()
  try {

    const aaaRes = await transaction.collection('account').doc('aaa').get()
    const bbbRes = await transaction.collection('account').doc('bbb').get()

    if (aaaRes.data && bbbRes.data) {
      const updateAAARes = await transaction.collection('account').doc('aaa').update({
        amount: dbCmd.inc(-10)
      })

      const updateBBBRes = await transaction.collection('account').doc('bbb').update({
        amount: dbCmd.inc(10)
      })

      const aaaEndRes = await transaction.collection('account').doc('aaa').get()
      if (aaaEndRes.data.amount < 0) { // 请注意transaction.doc().get()返回的data不是数组形式
        await transaction.rollback(-100)
        return {
          success: false,
          error: `rollback`,
          rollbackCode: -100,
        }
      } else {
        await transaction.commit()
        console.log(`transaction succeeded`)

        return {
          success: true,
          aaaAccount: aaaRes.data.amount - 10,
        }
      }

    } else {

      return {
        success: false,
        error: `rollback`,
        rollbackCode: -100,
      }
    }
  } catch (e) {
    await transaction.rollback()
    console.error(`transaction error`, e)

    return {
      success: false,
      error: e
    }
  }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值