V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
lhx2008
V2EX  ›  问与答

MySQL RR 级别 + FOR UPDATE 能否解决 Write Skew 问题?串行化可以解决吗?

  •  
  •   lhx2008 · Mar 2, 2020 · 1498 views
    This topic created in 2248 days ago, the information mentioned may be changed or developed.
    Write Skew 我的理解是这样的一个程序:

    if (select xxx 满足某个条件 X){
    do xxx 让条件 X 不满足;
    }

    在两个事务里面并发执行,并且在 do 之前条件是满足的。这样 do xxx 可能会执行一次,也可能会是两次。我们的要求是只能执行一次。


    对于已存在的行,select 用 FOR UPDATE 可以阻塞住第二个并发的 select,RC 和 RR 都不会出现 Write Skew 问题
    对于不存在的行,用 FOR UPDATE 无法挂行锁,RC 级别会出问题。RR 级别有间隙锁,有一些 do xxx 可能会因为间隙锁而造成死锁,最后只能执行一个事务,也可能间隙锁挂的位置不对而没有产生约束力(比如覆盖索引),从而 do 还是执行了两次,是这样的吗?

    另外,MySQL 的 串行化 似乎问题也同样存在,而 ddia 里面则说串行化可以解决,是我哪里理解错了?
    6 replies    2020-03-02 15:41:47 +08:00
    chenset
        1
    chenset  
       Mar 2, 2020   ❤️ 1
    类似的问题我是用动态用 RC + FOR UPDATE 解决的 , 不知道你的为什么又问题. 不太确定你跟场景是否一致
    lhx2008
        2
    lhx2008  
    OP
       Mar 2, 2020
    @chenset #1 如果行已经存在是可以的,如果行不存在,比如 count 一个条件是不是 = 0,是的话插一条让他不等于 0,就有可能插到两条。
    chenset
        3
    chenset  
       Mar 2, 2020   ❤️ 1
    FOR UPDATE 无法挂行锁: 对了我不是 row 锁, 而是 range 锁. 是不是这个概念不太清楚了,太久了. 反正锁定的是多行共用同值的索引, 而不是唯一锁
    chenset
        4
    chenset  
       Mar 2, 2020   ❤️ 1
    我的场景是针对同一个商品抢购, 通过合计抢购明细达到不超售的目的. RR 没法解决 转而使用 RC
    FaceBug
        5
    FaceBug  
       Mar 2, 2020   ❤️ 1
    超卖问题不应该由数据库解决吧,考虑下 redis 之类的

    实在要数据库解决,可以锁商品行,扣减余额字段,同时增加订单

    而不是锁订单范围吧
    chenset
        6
    chenset  
       Mar 2, 2020
    @cepczkd 楼主可能不是超售的场景, 简单的 sql 就能解决超售问题我就没有的引入太多功能. 锁金额 /数量增加了一个字段, 综合考虑起来后就这样了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5814 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 06:39 · PVG 14:39 · LAX 23:39 · JFK 02:39
    ♥ Do have faith in what you're doing.