-
MySQL 防止库存超卖的方案分析
在电商等高并发场景下,防止库存超卖是一个常见问题。以下是几种常见的解决方案及其优缺点分析:
1. 悲观锁 (FOR UPDATE)
BEGIN; SELECT stock FROM products WHERE id = 123 FOR UPDATE; -- 检查库存是否足够 UPDATE products SET stock = stock - 1 WHERE id = 123; COMMIT;优点:
- 实现简单直接
- 保证强一致性,不会出现并发问题
- 适合库存量少、竞争激烈的场景
缺点:
- 性能较差,高并发下容易成为瓶颈
- 可能导致死锁
- 锁粒度大,影响系统吞吐量
2. 乐观锁 (版本号或时间戳)
UPDATE products SET stock = stock - 1, version = version + 1 WHERE id = 123 AND version = #{oldVersion} AND stock > 0;优点:
- 无锁设计,性能较好
- 适合读多写少的场景
- 减少数据库锁竞争
缺点:
- 实现相对复杂
- 高并发下失败率高,需要重试机制
- 不保证每次请求都能成功
3. 直接库存检查 (库存>0)
UPDATE products SET stock = stock - 1 WHERE id = 123 AND stock > 0;优点:
- 实现最简单
- 性能较好
- 不需要额外字段
缺点:
- 在极高并发下仍可能出现超卖(虽然概率低)
- 无法区分具体失败原因
4. 其他方案
4.1 Redis原子操作 + 异步同步
- 使用Redis的DECR等原子操作
- 异步同步到数据库
- 适合秒杀等极端高并发场景
4.2 预扣库存
- 下单时预扣库存
- 支付成功时实际扣减
- 支付超时回滚库存
方案对比
方案 一致性 性能 实现复杂度 适用场景 悲观锁 强 低 简单 库存少,强一致要求 乐观锁 最终 高 中等 读多写少,可接受失败 直接检查 较强 高 简单 一般电商场景 Redis 最终 极高 复杂 秒杀等高并发 推荐方案
- 普通电商场景:直接使用
UPDATE ... WHERE stock > 0通常足够 - 高并发秒杀:Redis原子操作 + 异步同步 + 乐观锁
- 强一致性要求:悲观锁(但要控制锁持有时间)
- 分布式系统:考虑分布式锁或分库分表策略
-
MySQL 并发执行
UPDATE stock > 0的详细过程分析您提出了一个很好的问题:当事务A执行扣减后,事务B执行时库存已经为0,为什么
stock > 0条件还能满足?让我们深入分析MySQL的执行机制。1. MySQL的UPDATE语句执行流程
当执行
UPDATE products SET stock = stock - 1 WHERE id = 12
mysql 防止库存超卖,有哪些方案?
于 2025-05-06 17:19:29 首次发布

最低0.47元/天 解锁文章
314

被折叠的 条评论
为什么被折叠?



