baiyuxiong
V2EX  ›  问与答

开发中计算金额合计怎么算?

  •  
  •   baiyuxiong · Apr 22, 2020 · 2418 views
    This topic created in 2217 days ago, the information mentioned may be changed or developed.

    需求是: 用户参与活动报名,缴报名费,每次有人报名后,活动总共收到的报名费就要统计出来。 方法 1: update table set fee = fee + 10

    方法 2: $fee = "select sum(fee) from pay_log where ..." update table set fee = $fee

    大家都用什么方法保证不出错? 方法 1 和方法 2 是不是都必须加上事务?

    12 replies    2020-04-24 07:50:32 +08:00
    libook
        1
    libook  
       Apr 22, 2020
    最精确的肯定是每次从数据库里求和,但要看你量级多大,会不会导致性能问题。

    还有就是总额是展示给用户看的还是展示给老板看的,一般展示给用户看都不是真实的数量或金额。
    keepeye
        2
    keepeye  
       Apr 22, 2020
    用方法 1 ,和 pay_log 插入语句放到一个事务里
    方法 2 怕并发
    baiyuxiong
        3
    baiyuxiong  
    OP
       Apr 22, 2020
    @keepeye 方法 1 总感觉可靠性低,担心算错。
    baiyuxiong
        4
    baiyuxiong  
    OP
       Apr 22, 2020
    @libook 如果量级大就选择方法 1 ?
    keepeye
        5
    keepeye  
       Apr 22, 2020
    为什么担心算错?
    hua123s
        6
    hua123s  
       Apr 22, 2020 via iPhone
    在可重复读隔离级别下,update 是当前读,所以 1 和 2 是等价。我刚刚百度的,不知道对不对
    hua123s
        7
    hua123s  
       Apr 22, 2020 via iPhone
    看错,方法二不带 for update,方法二会脏读
    mwiker
        8
    mwiker  
       Apr 22, 2020
    没缴纳时间吗?
    libook
        9
    libook  
       Apr 22, 2020
    @baiyuxiong 并不是,只是说量大的话方案 2 性能会差,届时可能需要一些更复杂的方案来保障较强一致性的同时也能保障较高的可用性。

    举个例子:
    可以做两层,上层是快照层,用 Redis 等内存数据库来存当前的总额,又增加则在这个数字上直接累加;下层是持久层,记录每一条交易。
    服务读取总额的时候只从快照层读取当前总额,然后可以设置一个对持久层性能影响较小的刷新周期,比如 10 秒,每个刷新周期从持久层计算总额然后覆盖到快照层。当然这个方案还要考虑业务级别的事务,比如对两层进行写操作需要有原子性,要么都写成功,要么都失败。

    还可以更复杂,当然一切都是看实际情况,如果你量不大,没必要搞这么复杂,就每次求和就行了。
    wxF2BByt634kiAN1
        10
    wxF2BByt634kiAN1  
       Apr 22, 2020 via Android
    这种东西用户也不知道,有必要实时更新么。。
    CStarter
        11
    CStarter  
       Apr 22, 2020
    update table set fee = fee + 10 where fee = 原值

    一定要在更新 fee 时,校验 fee 是否为原值,否则可能出现并发问题。
    baiyuxiong
        12
    baiyuxiong  
    OP
       Apr 24, 2020
    @libook 666 这个方案感觉不错
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5325 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 59ms · UTC 05:51 · PVG 13:51 · LAX 22:51 · JFK 01:51
    ♥ Do have faith in what you're doing.