有懂秒杀的兄弟吗?为什么 mysql 这样会出现超卖的问题

2018-11-20 17:15:26 +08:00
 cyhulk
首先设定一个前提,为了防止超卖现象,所有减库存操作都需要进行一次减后检查,保证减完不能等于负数。(由于 MySQL 事务的特性,这种方法只能降低超卖的数量,但是不可能完全避免超卖)

update number set x=x-1 where (x -1 ) >= 0;
为什么这条语句会出现超卖
15573 次点击
所在节点    Java
84 条回复
lihongjie0209
2018-11-20 17:37:56 +08:00
你的事务级别是什么?
iloveyou
2018-11-20 18:09:01 +08:00
悲观锁乐观锁
WeaponXu
2018-11-20 18:15:42 +08:00
取数据的时候要锁一下
mmdsun
2018-11-20 18:24:33 +08:00
update number set x=x-1 where x >0 这样写肯定不会超卖的。RR 隔离级别
opengps
2018-11-20 18:25:49 +08:00
秒杀是个高并发的东西,不适合用数据库控制
gejun123456
2018-11-20 18:28:56 +08:00
你这样写肯定不会的
blue0125
2018-11-20 18:30:31 +08:00
据说用 Redis 可以
xavier007
2018-11-20 18:37:52 +08:00
队列!比如小米原来的秒杀,就是有个中间页,然后通过队列限制进入实际购买页。另外数据库更新也可以利用队列。这样限制了更新数据库的并发量
zjsxwc
2018-11-20 18:44:40 +08:00
这种 sql 明显会超卖的啊, mysql 默认的事务级别是允许幻读的, 使用队列处理秒杀是最佳实践.
ilyh
2018-11-20 19:22:13 +08:00
你这样写是不会的, mysql 默认的隔离级别是可重复读, update set 操作是当前读, 会加锁的. 和幻读没有关系
luozic
2018-11-20 19:23:21 +08:00
事务,你这只是 update,
heww
2018-11-20 19:24:05 +08:00
用 select for update 来做
o00o
2018-11-20 19:29:13 +08:00
艺高人胆大,我这都是在 Java 端用线程锁判断
limuyan44
2018-11-20 19:45:05 +08:00
mysql 默认的 rr 级别不会的,另,这个和上面说的幻读有毛关系。。
Raymon111111
2018-11-20 19:47:25 +08:00
这样写应该不会超卖啊
mayday526
2018-11-20 19:50:59 +08:00
默认级别 RR,理论上不会,那么问题来了,为什么这样还是会超卖呢
leriou
2018-11-20 19:55:24 +08:00
秒杀用 redis 分布式锁服务
insert000
2018-11-20 19:55:54 +08:00
当并发进来的时候 x-1 可能是同时的,并且 x 设置成非负
Va1n3R
2018-11-20 19:59:18 +08:00
了解一下安全界的条件竞争漏洞~
cheeseyu1994
2018-11-20 20:00:24 +08:00
这样会超卖吗?等答案|ω・)
是不是没有对 mysql 操作结果进行判断就直接写入订单了?

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

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

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

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

© 2021 V2EX