前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >最基础的账户余额要怎么在 mysql 实现?

最基础的账户余额要怎么在 mysql 实现?

作者头像
执生
发布2021-03-02 16:48:00
1K0
发布2021-03-02 16:48:00
举报
文章被收录于专栏:立权的博客

问题场景:

假设用户A的账户余额是 100

现在有两个事务 a,b

a 事务内容是 用户A消费 30 元

b 事物内容是 用户A消费 60 元

如果现在 a 和 b 互相不设防,无论 a 和 b 是什么事务隔离级别(除了序列化),最终结果都可能是错误的

模拟:

  1. 读提交情况下,这种情况没有正确可言

  2. a, b 均是 可重复读级别

    a 读取余额100  

              b 读取余额100

    a 写入余额70    b 也想写入余额40(被a加的行锁阻塞)

              b 写入余额40成功

  最终余额40,正确余额应该是 10

    a 读取余额 100   b 读取余额 100

    a 写入余额 70    

              b 写入余额 40

  同上

这种问题的本质是什么呢?可以类比SMP环境,即多核心处理器环境下的多线程/进程并发问题

将 a 和 b 比作是 两个线程/进程,一致性读就是只要一个线程/进程 他把对应的内容的缓存行读入自己的高速缓存

无论以后其他线程怎么改这个内容,他都只会读自己的高速缓存里的内容,所以每次读到的都不是最新值,当然也就存在经典的写覆盖问题了

  3. 任意一个事务使用 读提交,也是不可以的,任一未提交,都会读到同一个值,然后在此基础上修改,产生写覆盖

    a 读取余额100  

              b 读取余额100

    a 写入余额70    b 也想写入余额40(被a加的行锁阻塞)

              b 写入余额40成功

此类问题的本质是 对一个数据的读写不是原子的,中间可能有其他事务插进来 读/写

策略1,使用悲观锁

用悲观锁来保证事务 修改该数据的原子性

    a select 余额 ... for update (加写锁)  

    a 写入余额70           b 读取(阻塞)

    a 结束,释放所有锁        b 读取余额 70

                     b 写入余额 10   

策略2,使用乐观锁

    步骤1.a select 余额 ,读到100           b select 余额,读到 100

               b update 余额 = 40 where 余额 = 100

    a update 余额 = 70 where 余额 = 100(失败,回到步骤1重新读取余额,然后再次尝试)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-02-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档