赞
踩
问题描述: 压力高并发情况下 执行update方法 得到结果非预期结果
例如: 多个线程执行 充值金额方法
1、先查询出目前金额信息a
2、将充值的金额组装a(原金额+充值金额=新金额)
3、更新金额(执行update方法)
问题: 多并发的情况下, 会是多个线程同时读取到目前金额a , 之后 多个线程进行分别组装数据,依次更新, 这就导致 A账户本来有50元 两个并发线程同时充值50元 最终数据库中 账户只有100元,而不是150元(第二次更新覆盖第一次更新)
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(提交事务)
优化:
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(提交事务)
第二种加锁方案是一种悲观锁机制。而且SELECT...FOR UPDATE方式也不太常用,联想到CAS实现的乐观锁机制,于是我想到了第三种解决方案:乐观锁。
具体来说也挺简单,首先SELECT SQL不作任何修改,然后在UPDATE SQL的WHERE条件中加上SELECT出来的vip_memer的end_at条件。如下:
这样可以根据UPDATE返回值来判断是否更新成功,如果返回值是0则表明存在并发更新,那么只需要重试一下就好了。
可以在应用层使用一个分布式锁(可以放在Memcache中),控制同一时间,只允许一个应用实例进行查询并更新的操作。
相关推荐: 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(个人认为 这个写的还不错)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。