mysql处理高并发-保证数据准确性

问题描述: 压力高并发情况下  执行update方法 得到结果非预期结果

 

例如: 多个线程执行 充值金额方法

         1、先查询出目前金额信息a

         2、将充值的金额组装a(原金额+充值金额=新金额)

         3、更新金额(执行update方法)

问题: 多并发的情况下, 会是多个线程同时读取到目前金额a ,  之后 多个线程进行分别组装数据,依次更新,  这就导致  A账户本来有50元  两个并发线程同时充值50元  最终数据库中 账户只有100元,而不是150元(第二次更新覆盖第一次更新)

 

解决方案:

1、先更新(更新会锁表)  然后在查询   如果金额超出预期  直接回滚 ,更新中  将加减运算放在sql中执行 可以保证数据准确性。

beginTranse(开启事务)

try{

    //quantity为请求减掉的库存数量
    $dbca->query('update s_store set amount = amount - quantity where postID = 12345');

扫描二维码关注公众号,回复: 905157 查看本文章

    $result = $dbca->query('select amount from s_store where postID = 12345');

    if(result->amount < 0){

       throw new Exception('库存不足');

    }

}catch($e Exception){

    rollBack(回滚)

}

commit(提交事务)

优化:

beginTranse(开启事务)

try{

    //quantity为请求减掉的库存数量
    $dbca->query('update s_store set amount = amount - quantity where postID = 12345');

    $result = $dbca->query('select amount from s_store where postID = 12345');

    if(result->amount < 0){

       throw new Exception('库存不足');

    }

}catch($e Exception){

    rollBack(回滚)

}

commit(提交事务)

 

2、乐观锁,类CAS机制

    第二种加锁方案是一种悲观锁机制。而且SELECT...FOR UPDATE方式也不太常用,联想到CAS实现的乐观锁机制,于是我想到了第三种解决方案:乐观锁。

    具体来说也挺简单,首先SELECT SQL不作任何修改,然后在UPDATE SQL的WHERE条件中加上SELECT出来的vip_memer的end_at条件。如下:


vipMember = SELECT * FROM vip_member WHERE uid=1001 LIMIT 1 # 查uid为1001的会员
cur_end_at = vipMember.end_at
if vipMember.end_at < NOW():
   UPDATE vip_member SET start_at=NOW(), end_at=DATE_ADD(NOW(), INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001 AND end_at=cur_end_at
else:
   UPDATE vip_member SET end_at=DATE_ADD(end_at, INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001 AND end_at=cur_end_at

 

    这样可以根据UPDATE返回值来判断是否更新成功,如果返回值是0则表明存在并发更新,那么只需要重试一下就好了。

 

3、应用层分布式锁

可以在应用层使用一个分布式锁(可以放在Memcache中),控制同一时间,只允许一个应用实例进行查询并更新的操作。

 

4、使用队列

 

 

相关推荐: http://blog.csdn.net/asd1836382/article/details/46355703

http://www.jb51.net/article/50103.htm

http://blog.csdn.net/dujianxiong/article/details/54849091

http://blog.csdn.net/caomiao2006/article/details/38568825(个人认为  这个写的还不错)

猜你喜欢

转载自blog.csdn.net/lu930124/article/details/72772803