开发中计算金额合计怎么算? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
baiyuxiong
V2EX    问与答

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

  •  
  •   baiyuxiong 2020-04-22 16:16:48 +08:00 2087 次点击
    这是一个创建于 1997 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

    一定要在更新 fee 时,校验 fee 是否为原值,否则可能出现并发问题。
    baiyuxiong
        12
    baiyuxiong  
    OP
       2020-04-24 07:50:32 +08:00
    @libook 666 这个方案感觉不错
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2351 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 15:46 PVG 23:46 LAX 08:46 JFK 11:46
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86