处理库存超卖的情况前,先了解下什么是乐观锁和悲观锁,下面的几篇博客已经介绍的比较详细了,我就不在赘述其原理了

【MySQL】悲观锁&乐观锁

对mysql乐观锁、悲观锁、共享锁、排它锁、行锁、表锁概念的理解

下面开始介绍悲观锁在实际中的应用了

//下订单

..........
try {
M()->startTrans();
//判断商品是否有赠品
$give_gift=$ob->getGiveGoods($sku_nos);
if(!empty($give_gift)){
$this->dealSkuGift($give_gift,$ob,$data['order_no'],$skuNumArr,$packageSku);
}
}catch(FlException $ex) {
M()->rollback();
$curCode = $ex->getErrorCode();
$curmsg = $ex->getMessage();
E($curCode, $curmsg);
}
M()->commit();
..........

//获取赠品库存

public function getGiveGoodsStock($sku_no){
$sku_no=implode(",",array_unique($sku_no));
$sku_no = "'".str_replace(",","','",$sku_no)."'";
$Model = new \Think\Model();
$sku_gift_info=$Model->query("select sku_no,stock from ".C('DB_PREFIX')."sku_gift_stock where is_deleted=0 and is_online=1 and sku_no in($sku_no) for update");
return $sku_gift_info;
}

// 处理赠品

private function dealSkuGift($give_gift,$ob,$orderNo,$skuNumArr,$packageSku){
if(empty($give_gift) or empty($skuNumArr)){
return false;
}
$skuGiftStockM=M('sku_gift_stock');
$sku_gifts=array_column($give_gift,'sku_no');
//获取赠品库存
$sku_give_gift=$ob->getGiveGoodsStock($sku_gifts,);
$skuGiftStock=array();
$giftCount=;
foreach($sku_give_gift as $k=>$v){
$skuGiftStock[$v['sku_no']]=$v['stock'];
}
$public = new PModel();
foreach ($give_gift as $v){
$goodsNums=;
$delStockWhere=array();
if($v['isHaveStock']=='' && $skuGiftStock[$v['sku_no']] >){//代表有货--这些是需要发货的
if($v['type']==''){
$lastGiftNum=$skuNumArr[$v['parent_sku_no']]*$v['goods_nums'];
}else{//按固定赠品数量
$lastGiftNum=$v['goods_nums'];
}
if($lastGiftNum >= $v['stock_num']){
$lastGiftNum=$v['stock_num'];
}
if($v['stock_num']==){
$lastGiftNum=;
}
$delStockWhere['sku_no']=$v['sku_no'];
$delStockWhere['is_deleted']=;
$delStockWhere['is_online']=;
$delStockWhere['_string']= sprintf('stock>=%d', $lastGiftNum);
$skuGiftStockM->where($delStockWhere)->lock(true)->setDec('stock',$lastGiftNum);//扣除商品赠品库存
$re_v=$public->updataSignData($v['sku_no'],$lastGiftNum,'virtual_inventory','-','goods_sku','sku_no');//扣除赠品商品库存
if(false == $re_v){
E('');
}
$giftCount+=$lastGiftNum;
}else{
$lastGiftNum=;
}
$dd[]=array(
'parent_sku_no'=>$v['parent_sku_no'],
'sku_no'=>$v['sku_no'],
'num'=>$lastGiftNum,//最终发货的数量,无货为0
'create_time'=>date('Y-m-d H:i:s',time()),
'order_no'=>$orderNo,
'package_id'=>$packageSku[$v['parent_sku_no']],
'stock_num'=>empty($skuGiftStock[$v['sku_no']])?:$skuGiftStock[$v['sku_no']]
);
}
$order_goods_gift=M('order_goods_gift');
$order_goods_gift->addAll($dd); $upOrdeData=array(
'gift_count'=>$giftCount+
);
M('order')->where('order_no="'.$orderNo.'"')->data($upOrdeData)->save();
return true;
}

//接口访问方式

//由于要测试并发下该接口的超卖处理情况,所以访问接口前,可将body里的参数写死到接口内,这样方便调试

//再次访问接口

//下面就可以用apache的ab工具对下单接口进行并发测试了

到数据库里查看商品P002026-01关联了2个赠品,各关联了10个

查看赠品的库存数量

apache并发测试的原理及使用方法参见博客:https://www.cnblogs.com/lishuyi/p/5808661.html

使用方法:

ab -n 1 -c   http://app.zouke.com/
(-n发出10个请求,-c模拟5个并发,相当5人同时访问,后面是测试url) ab -t -c http://192.168.0.10/
在60秒内发请求,一次100个请求。

先预测下,请求10次,并发5个,最终的库存会剩余0

下面开始并发测试

最终赠品P002872、P002962的剩余库存如下

结果可见,本次悲观锁起了效果,下面看下不用悲观锁的情况会是什么样,下面将2个赠品的库存都恢复为10个,并将获取赠品库存代码进行改造,这次获取赠品库存是没加悲观锁的

//获取赠品库存
public function getGiveGoodsStock($sku_no,$ori){
$sku_gift=M('sku_gift_stock');
$sgg_where['sku_no']=array('in',$sku_no);
$sgg_where['is_deleted']=;
$sgg_where['is_online']=;
$sku_gift_info=$sku_gift->field('sku_no,stock')->where($sgg_where)->select();
return $sku_gift_info;
}

再次并发测试一下

发现赠品库存是变为负数了,这是超卖的情况出现了

好了,以上测试可以了,下面看下直接用操作数据表看下效果,按如下顺序执行,发现当执行完前4步后,用户B查询不到赠品库存信息,主要是因为此时赠品表已经锁住了

下面执行用户A第5步COMMIT,用户B查询赠品库存立马查询出来了

上述可见,mysql悲观锁对赠品库存超卖的处理流程的生效过程了

mysql悲观锁处理赠品库存超卖的情况的更多相关文章

  1. mysql处理高并发,防止库存超卖

    先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购一个商品.然而,作为活动商品,库存肯定是很有限的,如何控 ...

  2. Mysql在高并发情况下,防止库存超卖而小于0的解决方案

    背景: 本人上次做申领campaign的PHP后台时,因为项目上线后某些时段同时申领的人过多,导致一些专柜的存货为负数(<0),还好并发量不是特别大,只存在于小部分专柜而且一般都是-1的状况,没 ...

  3. <转> mysql处理高并发,防止库存超卖

    先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购 一个商品.然而,作为活动商品,库存肯定是很有限的,如何 ...

  4. MYSQL处理高并发,防止库存超卖(图解)

    抢购场景完全靠数据库来扛,压力是非常大的,我们在最近的一次抢购活动改版中,采用了redis队列+mysql事务控制的方案,画了个简单的流程图: 先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团 ...

  5. mysql 悲观锁与乐观锁的理解

    悲观锁与乐观锁是人们定义出来的概念,你可以理解为一种思想,是处理并发资源的常用手段. 不要把他们与mysql中提供的锁机制(表锁,行锁,排他锁,共享锁)混为一谈. 一.悲观锁 顾名思义,就是对于数据的 ...

  6. 记一次项目中解决 -- 并发减库存超卖问题过程(Java)

    起因:项目中要做预约功能,首先每天的余票都是有上限的,自然不能出现超卖的情况 基于我们项目是单体分布式的springcloud部署,我想了下 第一种方法,直接mysql加行锁,要update这条库存数 ...

  7. 《MySQL悲观锁总结和实践》乐观锁

    mysql乐观锁总结和实践 博客分类: MyBatis 数据库 mysql数据库乐观锁悲观锁 上一篇文章<MySQL悲观锁总结和实践>谈到了MySQL悲观锁,但是悲观锁并不是适用于任何场景 ...

  8. 【MySQL】MySQL悲观锁 + 事物 + for update 解决普通流量并发的问题

    使用mysql悲观锁解决并发问题   最近学习了一下数据库的悲观锁和乐观锁,根据自己的理解和网上参考资料总结如下: 悲观锁介绍(百科): 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事 ...

  9. 【分布式锁的演化】“超卖场景”,MySQL分布式锁篇

    前言 之前的文章中通过电商场景中秒杀的例子和大家分享了单体架构中锁的使用方式,但是现在很多应用系统都是相当庞大的,很多应用系统都是微服务的架构体系,那么在这种跨jvm的场景下,我们又该如何去解决并发. ...

随机推荐

  1. 什么是redis事务

    一.什么是redis事务? 可以一次性执行多条命令,本质上是一组命令的集合.一个事务中的所有命令都会序列化,然后按顺序地串行化执行,而不会被插入其他命令 二.Redis 事务可以做什么? 一个队列中, ...

  2. 安卓LED跑马灯 超炫酷的表白神器破解版

    链接:https://pan.baidu.com/s/11Wxll4iLdcEPq0wUBK6Ong 提取码:all4

  3. 06. Z字型变换

    题目: 提交01: class Solution { public String convert(String s, int numRows) { int length = 2*numRows-2; ...

  4. Python 基础之匿名函数 迭代器和高阶函数

    一.匿名函数 lambda表达式 用一句话来表达只有返回值的函数,叫匿名函数特点:简洁方便语法:lambda 参数: 返回值 1.不带有参数的lambda表达式 def func():    retu ...

  5. 设计模式课程 设计模式精讲 14-2 组合模式coding

    1 代码演练 1.1 代码演练1(组合模式1) 1.2 代码演练2(组合模式1之完善) 1 代码演练 1.1 代码演练1(组合模式1) 需求: 打印出木木网的课程结构, 我们用一个组建类作为接口,课程 ...

  6. [python]ubuntu下的python2和python3

    在终端分别输入python,python2,python3python和python2默认都是python2python3才是python3 Ubuntu下是默认没有pip的,需要自己手动安装 sud ...

  7. JAVA关于回文判断的实现

    (一). 设计思想: 首先输入字符串,然后判断长度若长度为0或1则输出TRUE若长度大于一则进行判断, 若符合条件则输出TRUE反之输出FALSE. (二)程序源代码 import java.util ...

  8. Spark调优(三) JVM调优

    调节Executor堆外内存 概述: Spark底层shuffle的传输方式是使用netty传输,netty在进行网络传输的过程会申请堆外 内存(netty是零拷贝),所以使用了堆外内存. 什么时候需 ...

  9. mysql5.6源码安装(转)

    mysql5.6源码安装 转自 jabbok博客园 https://www.cnblogs.com/jabbok/p/9418344.html 1 编译安装 1 2 3 4 5 6 groupadd ...

  10. SpringBoot之Feign调用方式比较

    一:事发原因 两个东家都使用SpringCloud,巴拉巴拉用上了Spring全家桶,从eureka到ribbon,从ribbon到feign,从feign到hystrix,然后在使用feign的时候 ...