在商城中,有一件商品有100件库存,那么用户每购买一件,库存要做减一。 刚开始我想到这样进行处理:
$model = new Model(); //读取商品的库存 $quantity = $model->where(" id = 1 ")->count(); //库存减一 $quantity--; $result = mysql_query("UPDATE goods SET quantity = $quantity WHERE id = 1 ");
这样的方式,在不考虑并发的情况下是没问题的,但如果有多个用户同时操作,情况就不一样了。
假设两个用户同时购买,A用户读取库存为10,B用户读取库存也是10,A购买完成后,将库存减一,改为9, 而此时,B也将库存减一,改为9。实际卖出了两件,但库存没有正确减少,就会造成“超卖”。
A、B用户的购买流程是交叉执行的。
问题的关键在于上面的代码使用了两条SQL语句,所以造成了不同用户的请求可能交叉执行。 如果能将操作合并到一条SQL语句中,就可以避免这个问题。
请看修改后的代码:
$model = new Model(); $result = mysql_query("UPDATE goods SET quantity = quantity - 1 WHERE id = 1 ");
由于关系型数据库都是存储在文件中,对同一条记录的修改不能同时进行。这意味着即使A、B用户同时购买,修改库存时也是按先后顺序来的,因此库存可以正确的减少。
还有一个问题,如果库存已经为0了,上面的代码就有问题了,因为没有检查库存。
有两种方法解决该问题:
1、将quantity字段设为unsigned,当库存为0时,因为字段不能为负数,将会返回false。
2、修改SQL语句和实现代码:
$model = new Model(); //读取商品的库存 $quantity = $model->where(" id = 1 ")->count(); //库存减一 $quantity--; $result = mysql_query("UPDATE goods SET quantity = quantity - 1 WHERE id = 1 WHERE quantity > 0 "); $num = mysql_affected_rows(); if($num == 1){ //成功 }
如果库存为0了,受影响的行将为0,意味着购买失败。
时间: 2024-10-07 01:26:37