秒杀或者活动商品的超卖问题是在商城项目都会存在的一个问题,这个问题也是属于高并发场景下产生的问题之一,主要是因为并发过大,导致商品出售超出库存。
MySQL 排它锁
<?php
try{
$pdo=new pdo("mysql:host=localhost;dbname=mysql_php","root","root",array(PDO::ATTR_AUTOCOMMIT=>0));//最后是关闭自动提交
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);//开启异常处理
try{
$pdo->beginTransaction();//开启事务处理
$product_id = 1;//商品ID号
$sql = "select * from product where id = {$product_id} for update";
$restful = $pdo->query($sql)->fetch(PDO::FETCH_ASSOC);
if(!$restful){
$pdo->rollback();//事务回滚
echo "商品不存在:".$e->getMessage();
exit;
}else{
if($restful['product_stock'] <= 0){
$pdo->rollback();//事务回滚
echo "修改库存失败,库存不足";
exit;
}else{
$version = $restful['version'];
$sql = "update product set product_sock=product_sock-1 where id = {$product_id}";
$restful = $pdo->exec($sql);
if($restful){
$pdo->commit();//事务提交
echo "修改库存成功";
exit;
}else{
echo "修改库存失败";
$pdo->rollback();//事务回滚
exit;
}
}
}
} catch (\Exception $e){
$pdo->rollback();//事务回滚
echo $sql.$e->getMessage();
exit;
}
} catch (\Exception $e){
echo "数据库连接失败:".$e->getMessage();
exit;
}
?>
先进行商品的查询并加上一把排它锁,判断商品是否存在以及商品的库存是否大于 0 的,因为在查询的时候加了排它锁,所以数据并不属于缓存查询的数据,而是磁盘中实际的,属于当前读。如果此时其他事务进行查询,会进入锁等待,直到他得到锁为止。