zoukankan      html  css  js  c++  java
  • 最基础的账户余额要怎么在 mysql 实现?

    问题场景:

    假设用户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重新读取余额,然后再次尝试)

        

        

  • 相关阅读:
    ByteBuffer用法总结
    内部类访问外部同名属性或者方法
    floodlight 学习(一)
    ubuntu 更改文件所有者
    python cmd 模块
    matlab 矩阵
    python操作MySQL数据库
    Win 7 下制作 mac 系统启动U盘
    Window 常用命令
    大数据扫盲
  • 原文地址:https://www.cnblogs.com/lqlqlq/p/14388358.html
Copyright © 2011-2022 走看看