收藏
回答

事务的快照隔离 能否保证读的一致性?

小程序文档:

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/transaction.html

疑惑点:

问题举例:

账户aaa中有100元,并发发起多个转账操作-100,那么能否在事务中,通过 读账户余额,判断余额<100时就中断转账,而避免把账户减成负数。

例代码:

const result = await db.runTransaction(async transaction => {
      const aaaRes = await transaction.collection('account').doc('aaa').get()

      if (aaaRes.data.amount >= 100 ) {
        const updateAAARes = await transaction.collection('account').doc('aaa').update({
          data: {
            amount: _.inc(-100)
          }
        })

        const updateBBBRes = await transaction.collection('account').doc('bbb').update({
          data: {
            amount: _.inc(100)
          }
        })

        console.log(`transaction succeeded`, result)

        return {
          aaaAccount: aaaRes.data.amount - 100,
        }
      } else {
        await transaction.rollback(-1)
      }
    })

    return {
      success: true,
      aaaAccount: result.aaaAccount,
    }


问题:能够通过事务按上述代码来满足这种需求呢?

最后一次编辑于  2021-06-30
回答关注问题邀请回答
收藏

2 个回答

  • yufei
    yufei
    2021-06-30

    我模拟操作了几次,日志显示可以保证每次判断的是最新值,不知道这是不是快照隔离的1,2两点。

    2021-06-30
    有用
    回复
  • A哆啦梦
    A哆啦梦
    2021-06-30

    这里不应该是避免把账户减成负数,而是避免减了多次以后账户是0

    2021-06-30
    有用
    回复 4
    • yufei
      yufei
      2021-06-30
      感谢回复,0或负数不是关键,关键是保证并发的每次减都是基于现有余额,每次减都可以判断余额。
      2021-06-30
      回复
    • A哆啦梦
      A哆啦梦
      2021-06-30回复yufei
      我想多了,这里根据业务回滚就行了,代码看起来是对的
      2021-06-30
      回复
    • yufei
      yufei
      2021-07-01回复A哆啦梦
      谢谢
      2021-07-01
      回复
    • 游戏客
      游戏客
      2022-07-11
      虽然说是一个快照做比对,最怕是并发超卖(金额或者库存变为负数)的情况,理论上上面的代码对于防超卖没有任何作用,同一个时间点,100个请求都在同一时间amount >= 100条件达成的时候,下面的自减又同时改变了快照,争相拿到事务锁,轮候-100,amount不知道是否变成负一万。
      2022-07-11
      回复
登录 后发表内容