PHP+SQL库存校验问题:库存不足仍允许购买求错误排查
问题分析与解决方案
你的代码里有两个关键问题,导致库存检查完全没起到作用,让我给你拆解清楚:
1. 没有针对当前购买的商品查询库存
你已经通过$_GET['ID']拿到了用户要购买商品的$productID,但你的SQL查询SELECT stocklevel FROM products根本没用到这个ID!这会返回数据库里所有商品的库存数据,而$results->fetch()只会取结果集中的第一行——也就是说,你检查的永远是数据库里第一个商品的库存,和用户实际要下单的商品完全不相关!
正确的做法是在SQL里加上WHERE条件锁定当前商品,而且为了避免SQL注入风险,一定要用预处理语句:
// 用预处理查询当前商品的库存 $stmt = $conn->prepare("SELECT stocklevel FROM products WHERE id = ?"); $stmt->execute([$productID]); $row = $stmt->fetch();
2. 并发场景下的超卖隐患(隐藏坑)
就算你修复了上面的问题,还有一个容易忽略的风险:当多个用户同时购买同一件商品时,可能出现“超卖”——比如库存剩1,两个用户同时通过了stocklevel >=1的检查,然后都执行扣减操作,最终库存变成-1。
解决这个问题的最优方案是把库存检查和扣减合并成一个原子性的SQL操作,直接让数据库来保证逻辑的正确性:
// 只有当库存>=1时,才执行扣减操作 $stmt = $conn->prepare("UPDATE products SET stocklevel = stocklevel - 1 WHERE id = ? AND stocklevel >= 1"); $stmt->execute([$productID]); // 通过受影响行数判断操作是否成功 if($stmt->rowCount() === 0) { // 没有行被修改,说明库存不足 echo "抱歉,该商品库存不足,无法购买"; } else { // 库存扣减成功,继续处理订单逻辑(比如插入订单记录) // ... 你的订单创建代码 }
这种方式不需要先查询再更新,直接在数据库层面保证了操作的原子性,从根源上杜绝了超卖问题。
内容的提问来源于stack exchange,提问作者Ewelina Singh
相关产品推荐
相关产品推荐

