加了悲观锁,
加了泄洪队列,
加了限流,
还会出现
我想先了解下这个操作的逻辑
一般修改数据有两种逻辑
两种方案的区别
方案1应用端能处理比较复杂的逻辑,并不限于余额校验,还有其他的一些规则等等,自由管控;缺点,如果查询与写入存在足够的时间差,并发的动作可能将数据修改异常,举个例子
客户余额10, a 动作扣款1, b动作扣款2,查询与扣款中间间隔 10秒(极端情况),那么
a动作,查到余额是 10, 本次扣款1,理论上扣款后余额为 9
假如 a做完之后再做b,那么b查到的余额是 9,扣款2,计算出结果为 7,写入数据库,这个结果和我们期望一致
那么假如a还没做完写入动作,b就开始了呢,b当时查到的 余额还是10,b计算了,扣款之后是 8,后面还存在两种可能,b先做完,那么余额为9, a先做完,那么余额为8,不管哪种结果,都不符合我们预期
这种时候需要控制的东西会比较多,如果是一个服务端,一般不存在这种情况;多个服务端做负载的时候,这种问题有可能发生,比较常规的处理办法是 查询时做行锁,同时不读脏数据
方案2,数据库本身对某行数据的修改都是串行的,不存在冲突。这种update也不关心原始值是多少,只关心变化。缺点是部分逻辑校验不好处理,比如余额为负这种情况,可能需要另外结合数据库的约束处理,应用端接收各种异常并作正确响应
最佳答案 2020-03-24 17:09
我想先了解下这个操作的逻辑
一般修改数据有两种逻辑
两种方案的区别
方案1应用端能处理比较复杂的逻辑,并不限于余额校验,还有其他的一些规则等等,自由管控;缺点,如果查询与写入存在足够的时间差,并发的动作可能将数据修改异常,举个例子
客户余额10, a 动作扣款1, b动作扣款2,查询与扣款中间间隔 10秒(极端情况),那么
a动作,查到余额是 10, 本次扣款1,理论上扣款后余额为 9
假如 a做完之后再做b,那么b查到的余额是 9,扣款2,计算出结果为 7,写入数据库,这个结果和我们期望一致
那么假如a还没做完写入动作,b就开始了呢,b当时查到的 余额还是10,b计算了,扣款之后是 8,后面还存在两种可能,b先做完,那么余额为9, a先做完,那么余额为8,不管哪种结果,都不符合我们预期
这种时候需要控制的东西会比较多,如果是一个服务端,一般不存在这种情况;多个服务端做负载的时候,这种问题有可能发生,比较常规的处理办法是 查询时做行锁,同时不读脏数据
方案2,数据库本身对某行数据的修改都是串行的,不存在冲突。这种update也不关心原始值是多少,只关心变化。缺点是部分逻辑校验不好处理,比如余额为负这种情况,可能需要另外结合数据库的约束处理,应用端接收各种异常并作正确响应