mysql 减库存并发问题

2021-11-20 11:51:43 +08:00
 kikione

减库存数量为 num

update mytable set inventory = inventory-num WHERE id= 1 and inventory >=num

这样减库存不用加乐观锁和悲观锁,也可以是吧

但是有什么弊端吗

5410 次点击
所在节点    MySQL
47 条回复
Chad0000
2021-11-22 10:24:59 +08:00
@sujin190 #40

下单最后又失败了:订单系统做最终一致性检查,对于失败的已经出库的,及时通知库存回库,简单讲你下单后,生成一个若干分钟后的任务检查是否完成支付和出库。下单前已经锁定库存,所以有时间差也不会导致超卖除非锁库超时自动退回。

超卖问题:这个无法完全避免,你总会在各个流程遇到意外情况:比如拖着不付款或付款时间太长的,导致锁库超时已返回库存。这时下单使用的就是未锁定的库存 - 不能保证有货。付款锁定和库存锁定这两个东西即使一致也无法保证出库,因为付款可以因为第三方支付而拖时间。所以都只能满足大部分场景,然后通过最终一致化完成少数不正常的。
shanghai1943
2021-11-22 10:33:18 +08:00
不考虑高并发的话,这种实现方式简单,只要判断 affected rows 是否等于 1 就行了。
haython
2021-11-22 11:16:22 +08:00
淘宝以前就是这么干的
hangszhang
2021-11-22 12:37:26 +08:00
没问题,就是性能不高
dgr007
2021-11-22 12:45:52 +08:00
没问题,性能很好的
可能需要解决的是单条记录热点更新问题
bsg1992
2021-11-23 10:13:01 +08:00
SQL 没问题
你这个就是乐观锁,弊端就是并发量大的话会导致更新失败。
特别是针对某条热点数据会一直失败,这个需要解决一下。
一般这种情况你看的场景
1.是否允许超卖,不允许超卖的话另开一个监控程序发现超卖就直接退款 /或者不发货 当然这个是业务层面上的解决方案。
2.用队列进行消费,看你消费端的速度了。
3.就是实时计算库存数量,根据消耗库存记录算出来剩余库存
hui314
2021-11-23 10:55:05 +08:00
不想改动的话,有个最简单方法,新增一个字段 version,减库存 sql:update mytable set inventory = inventory-num , version = version+1 WHERE id= 1 and inventory >=num and version = {version};
即使并发也只有一个能成功,但是这样的话,只能一个人成功下单。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/816733

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX