mysql数据库并发修改时出现的数据错误

问题现象
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,第二次更新操作发现更新次数不等于刚刚查询出来的次数,更新无效

致此问题完美解决!

延伸思考

更新的问题如此,插入的问题依旧。

解决

每个人每一期只允许有一条记录,期号对于每个人来说是唯一的,但对于所有人来说又不唯一,每个人的id唯一,对于不同期的id又不唯一,那么期号+id就是每个人当期的唯一值,可以建立个新字段,写入时把当期期号+id写进去,如果高并发写入时,发现这个字段值存在,写入失败。抛出异常,执行更新操作 。亦可以多列联合唯一,这样就不用多加唯一字段拉!

一些个人拙见:欢迎拍砖!_欢迎指正错误

猜你喜欢

转载自blog.csdn.net/Sncdma/article/details/107853524
今日推荐