TangMonk
V2EX  ›  问与答

PostgreSQL 并发问题:下单之前检查商品数量是否足够,如果足够则购买后数量递减

  •  
  •   TangMonk · Jun 1, 2016 · 2597 views
    This topic created in 3650 days ago, the information mentioned may be changed or developed.

    用的默认的 Read Committed 并发控制,会不会出现多余的订单?

    比如说现在有 100 个订单,会不会出现 100+个订单?

    23 replies    2016-06-03 17:42:20 +08:00
    ipconfiger
        1
    ipconfiger  
       Jun 1, 2016
    要用 Serializable 才行
    TangMonk
        2
    TangMonk  
    OP
       Jun 1, 2016
    @ipconfiger 读取数量和递减数量的时候都用 Serializable 吗?
    tabris17
        3
    tabris17  
       Jun 1, 2016
    update product set inventory=inventory-1 where product_id=123 and inventory>=1
    TangMonk
        4
    TangMonk  
    OP
       Jun 1, 2016
    @tabris17 默认就是这样的。。
    tabris17
        5
    tabris17  
       Jun 1, 2016
    @TangMonk 你是说先 select 出 inventory ,然后 update 语句里不判断 inventory ?那必须 Serializable 隔离级别或者加锁
    TangMonk
        6
    TangMonk  
    OP
       Jun 1, 2016
    @tabris17 恩,对,先 select 出数量,然后再 update, 并且没有判断数量>=1 。
    TangMonk
        7
    TangMonk  
    OP
       Jun 1, 2016
    @tabris17 今天出现了这个问题,系统预先设置了 1000 个库存,然后后台发现 1008 个订单。。但是商品的数量还是为 0 ,并没有为-8 。。
    tabris17
        8
    tabris17  
       Jun 1, 2016
    @TangMonk 如果是 set inventory=inventory-1 不会出现这种情况,除非你是 set inventory=?
    jjx
        9
    jjx  
       Jun 1, 2016
    版本机制

    或用队列

    最安全的就是队列+版本机制
    imzshh
        10
    imzshh  
       Jun 1, 2016
    关键词: select for update
    TangMonk
        11
    TangMonk  
    OP
       Jun 1, 2016
    @tabris17 的确,用的就是 set inventory=?
    TangMonk
        12
    TangMonk  
    OP
       Jun 1, 2016
    @imzshh 谢谢,我搜下
    TangMonk
        13
    TangMonk  
    OP
       Jun 1, 2016
    @imzshh FOR UPDATE 不会锁住 SELECT 吗?只会锁 UPDATE , DELETE 和 FOR UPDATE 吗?
    TangMonk
        14
    TangMonk  
    OP
       Jun 1, 2016
    FOR UPDATE 貌似要比 Serializable 好用点
    TangMonk
        15
    TangMonk  
    OP
       Jun 1, 2016
    @tabris17 为什么 set inventory=inventory-1 不会出现这种情况呢
    imzshh
        16
    imzshh  
       Jun 1, 2016
    @TangMonk 你自己做些测试吧,因为这个要配合事务一起用的,所以实现的时候要考虑的东西还挺多的,程序异常,死锁之类的。
    TangMonk
        17
    TangMonk  
    OP
       Jun 1, 2016
    @imzshh 好的,谢谢
    tabris17
        18
    tabris17  
       Jun 1, 2016
    @TangMonk 因为字段自减是原子操作
    TangMonk
        19
    TangMonk  
    OP
       Jun 1, 2016
    @tabris17 刚才我开了几个线程请求测试了下,貌似不行,库存为 1000 ,库存递减到 0 的时候,才生成了 500 多个订单。。。

    我换成 FOR UPDATE , 测试了下没有问题了。

    看来要得好好补习下 MVCC 了
    TangMonk
        20
    TangMonk  
    OP
       Jun 1, 2016
    @TangMonk 读和写的都用 FOR UPDATE 锁住了
    wdrsam
        21
    wdrsam  
       Jun 3, 2016
    握草,楼主你们是某软 11 级,前身 andware ,大神是薛大神的那个团队?
    TangMonk
        22
    TangMonk  
    OP
       Jun 3, 2016
    @wdrsam 是,你怎么知道?!你是?
    wdrsam
        23
    wdrsam  
       Jun 3, 2016
    @TangMonk 之前在这看到你们发的招聘, @andware 后缀就想起了,哈哈。我也是某软 11 级的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2774 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 67ms · UTC 10:05 · PVG 18:05 · LAX 03:05 · JFK 06:05
    ♥ Do have faith in what you're doing.