高并发库存扣减超卖问题解决,多种sql适合场景分析

方案一: id是主键索引的前提下,如果每次只是减少1个库存,则可以采用上面的方式,只做数据安全校验,可以有效减库存,性能更高,避免大量无用sql,只要有库存就也可以操作成功.
场景:高并发场景下的取号器,优惠券发放扣减库存等

update product set stock=stock-1 where id = 1 and stock>0

方案二: 使用业务自身的条件做为乐观锁,但是存在ABA问题,对比方案三的好处是不用增加version版本字段。如果只是扣减库存且不在意ABA问题时,则可以采用上面的方式,但业务性能相对方案一就差了点,因为库存变动后sql就会无效

update product set stock=stock-1 
where stock=#{原先查询的库存} and id = 1 and stock>0

方案三: 增加版本号主要是为了解决ABA问题,数据读取后,更新前数据被别人篡改过,version只能做递增
场景:商品秒杀、优惠券方法,需要记录库存操作前后的业务

update product set stock=stock-1,versioin = version+1 
where id = 1 and stock>0 and version=#{原先查询的版本号} 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这个问题可以回答。对于高并发订单库存问题,需要考虑多线程并发和数据库事务的管理。以下是一个示例代码: ```java public class OrderService { private final InventoryDao inventoryDao; public OrderService(InventoryDao inventoryDao) { this.inventoryDao = inventoryDao; } // 库存,返回值为是否成功 public boolean reduceStock(int itemId, int quantity) { int stock = inventoryDao.getStock(itemId); if (stock < quantity) { return false; } return inventoryDao.reduceStock(itemId, quantity); } } public class InventoryDao { // 获取库存 public int getStock(int itemId) { String sql = "SELECT quantity FROM inventory WHERE item_id = ?"; try (Connection conn = getConnection(); PreparedStatement statement = conn.prepareStatement(sql)) { statement.setInt(1, itemId); try (ResultSet rs = statement.executeQuery()) { if (rs.next()) { return rs.getInt("quantity"); } } } catch (SQLException e) { throw new RuntimeException(e); } return 0; } // 库存,返回值为是否成功 public boolean reduceStock(int itemId, int quantity) { String sql = "UPDATE inventory SET quantity = quantity - ? WHERE item_id = ?"; try (Connection conn = getConnection()) { conn.setAutoCommit(false); try (PreparedStatement statement = conn.prepareStatement(sql)) { statement.setInt(1, quantity); statement.setInt(2, itemId); int affectedRows = statement.executeUpdate(); if (affectedRows == 1) { conn.commit(); return true; } } conn.rollback(); } catch (SQLException e) { throw new RuntimeException(e); } return false; } private Connection getConnection() throws SQLException { // 获取数据库连接 } } ``` 在这个示例代码中,OrderService 是对外提供的服务类,它依赖于 InventoryDao 来管理库存。reduceStock 方法是库存的核心方法,它首先从数据库中获取当前库存数量,然后检查是否足够。如果足够,就开启一个数据库事务,更新库存数量,最后提交事务。如果不足够,就直接返回 false 表示失败。 在实际使用中,需要根据具体场景进行优化,比如使用连接池来提高数据库连接的性能,采用分布式锁来控制并发等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值