问题现象
H5 游戏 ,线上用户报bug说账户余额信息与交易流水对不上。可以认为是数据库并发更新问题,由此定位出具体原因,并给出解决方案。
场景描述
后台给用户充值或提现时,且高并发量的情况下,出现充值100元(假设当前用户余额为50元)与此同时用户又下注10元,此时用于产生两条帐变信息,结果应该是
1变动金额 10 变动后余额 40 内容“下注”
2变动金额100 变动后余额 140 内容“充值”
或者
1变动金额100 变动后余额 150 内容“充值”
2变动金额 10 变动后余额 140 内容“下注”
但是
账变信息表表现为
1变动金额100 变动后余额 150 内容“充值”
2变动金额 10 变动后余额 40 内容“下注” 此处应该为 变动后余额140
导致用户变动后余额错误。
环境说明
mysql5.6 + innodb + php5.6
场景模拟
具体操作为
select money from user where id=x;
update usercoinlog set bdmoney = 刚刚查到的余额+变动金额 WHERE userid=x;
问题出现了
原因定位
假如后台充值和用户下注同时进行,同时查到的余额为50,再做update更新时把50拿来作为参照记录就会出现上述错误!
解决方案
方案一
增加数据库锁,不过这个玩意儿有一定弊端,后续再做介绍
方案二
在查询的时候取出来一个 字段值,比如叫 更新次数,在更新的时候我 update 表 set Money=Money-50, 更新次数=更新次数+1 where userid=123 and 更新次数=刚刚查询出来的次数,比如并发过来了两次查询结果都是50,但执行更新总有个先后的,这时候Money-50 同时更新次数也+1,第二次更新操作发现更新次数不等于刚刚查询出来的次数,更新无效
致此问题完美解决!
延伸思考
更新的问题如此,插入的问题依旧。
解决
每个人每一期只