update (['stock' => $sku->stock - $amount]) 最后不也是生成 SQL 语句直接操作吗?

update(['stock' => $sku->stock - $amount])

$this->newQuery()->where('id', $this->id)->where('stock', '>=', $amount)->decrement('stock', $amount);
的区别是什么?为什么下面这个可以用于高并发场合?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
leo
最佳答案

假如当前 SKU 库存为 1,这个时候同时进来两个 $amount=1下单请求,此时查到的 stock 都是 1,如果用 update(['stock' => $sku->stock - $amount]) ,那么最终结果是数据库中的 stock 变成了 0,并且两个订单都创建成功了,那么就出现了只有一个库存却卖出了两份,就是『超卖』。

5年前 评论
讨论数量: 19
leo

假如当前 SKU 库存为 1,这个时候同时进来两个 $amount=1下单请求,此时查到的 stock 都是 1,如果用 update(['stock' => $sku->stock - $amount]) ,那么最终结果是数据库中的 stock 变成了 0,并且两个订单都创建成功了,那么就出现了只有一个库存却卖出了两份,就是『超卖』。

5年前 评论

@leo 两者在处理库存的过程中使用了不同的锁机制吗?

5年前 评论
leo

@jingzhognwa 这个和锁没有关系

5年前 评论

@leo update的时候也可以加上

file这句避免问题

5年前 评论

@leo update的时候也可以加上

file这句避免问题

5年前 评论

这样的话我还是想知道decrement 或者increment里面做了啥操作

5年前 评论

@leo 老师,时隔三个月翻到这篇答案,还是不理解,可以帮忙解释下吗

4年前 评论

@leo 大佬能否解释下为何使用$this->newQuery()->where('id', $this->id)->where('stock', '>=', $amount)->decrement('stock', $amount);就不会出现并发超卖?谢谢!

4年前 评论
leo

@Neymar 课程文章里已经说得很清楚了

4年前 评论

这就是多个判断,高并发场景下,该超卖的还是会超卖。

4年前 评论

@leo 我发现 ,如果库存是0 ,之后在运行 decrement('stock',1) 在减1, 那这条sql 是报错的, 如果sql报错了,那他返回的是什么?

if ($sku->decreaseStock($data['amount']) <= 0){\
throw new InternalException('该商品已售卖完');\
}

这个if 得到的一个结果是 sql “错误” <= 0 ,这样也可以对比吗?

4年前 评论
leo

@jxdr 报什么错?

4年前 评论

@leo 你看看。 我了现, 如果减少成功 , 那会返回一个 1 ,失败了就是报错。

file

4年前 评论
leo

@jxdr 课程里用的是 decreaseStock,是自己写的 SQL

4年前 评论

@leo 我知道你的意思 ,

你是说课程里是用的那个定义的。

Laravel
这个是吧,
可是,里面和执行的代码和我的是一样的啊。

4年前 评论
leo

@jxdr 完全不一样,仔细看课程里的每一句话

4年前 评论

@jxdr 你这个报错是因为库存字段是unsigned的 ,变成负数的报错吧

4年前 评论

@leo 不好意思关于价格精度问题我想问你一下, 直接小数和整数也就是数量相乘会有精度问题嘛? 例如 0.58*10 这种情况, 我在想我们这个直接相乘会不会有精度问题, 或者说需要使用一些第三方库 类似bc这种, 如果不会产生精度问题能麻烦告知一下为啥嘛? 非常感谢!不胜感激

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!