小蒋同学

小蒋同学

· PHPMySQL · · 526次浏览

MySQL 处理高并发 防止库存超卖

1695043.jpg

问题描述

一般电子商务网站都会遇到如团购、秒杀、特价之类的活动,而这样的活动有一个共同的特点就是访问量激增、上千甚至上万人抢购一个商品。

然而,作为活动商品,库存肯定是很有限的,如何控制库存不让出现超卖,以防止造成不必要的损失,是众多电子商务网站程序员头疼的问题,这同时也是最基本的问题。

条件

总库存:4个商品
请求人:a、1个商品 b、2个商品 c、3个商品

错误示例

$pdo->beginTransaction();
try{
    $result = $pdo->query('select amount from s_store where postID = 12345');
    if($result->amount > 0){
        // quantity 为请求减掉的库存数量
        $pdo->query('update s_store set amount = amount - quantity where postID = 12345');
    }
    // 没有错误则提交事务
    $pdo->commit();
}catch($e \PDOException){
    // 遇到错误则回滚事务
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage();
}

使用 SELECT ... FOR UPDATE

$pdo->beginTransaction();
try{
    // 使用 SELECT ... FOR UPDATE 将此行数据锁住,在提交事务或者回滚事务时自动解开。
    $result = $pdo->query('select amount from s_store where postID = 12345 for update');
    if($result->amount < 0){
        // 抛出异常
        throw new \PDOException('库存不足');
    }
    // quantity 为请求减掉的库存数量
    $pdo->query('update s_store set amount = amount - quantity where postID = 12345');
    // 没有错误则提交事务
    $pdo->commit();
}catch($e \PDOException){
    // 遇到错误则回滚事务
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage();
}

其他方法

$pdo->beginTransaction();
try{
    // quantity 为请求减掉的库存数量
    $pdo->query('update s_store set amount = amount - quantity where postID = 12345');
    $result = $pdo->query('select amount from s_store where postID = 12345');
    if($result->amount < 0){
        // 抛出异常
        throw new \PDOException('库存不足');
    }
    // 没有错误则提交事务
    $pdo->commit();
}catch($e \PDOException){
    // 遇到错误则回滚事务
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage();
}
评论功能已被作者关闭