2018-05-27如何处理PHP高并发下数据库值更新的问题

您现在的位置是: 首页 > PHP技术 > 如何处理PHP高并发下数据库值更新的问题

355次阅读


一、创建一个测试数据库test ,创建商品表goods(字段id,total),商品id是1,商品总数10


CREATE TABLE `goods` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `total` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

INSERT INTO `goods` VALUES ('1', '10');


二、PHP模拟秒杀购买,商品数量大于0才能购买


<?php

$dbms = 'mysql';     //数据库类型
$host = '127.0.0.1'; //数据库主机名
$dbName = 'test';    //使用的数据库
$user = 'root';      //数据库连接用户名
$pass = '';          //对应的密码
$dsn = "$dbms:host=$host;dbname=$dbName";

try {

    $pdo = new PDO($dsn, $user, $pass); //初始化一个PDO对象
    echo "连接成功<br/>";

    // 查询id为1的记录
    $select_sql = "SELECT total FROM goods WHERE id=1 LIMIT 1";
    $result = $pdo->query($select_sql);
    $res = $result->fetch();
    if($res['total']>0){
        $update_sql = "UPDATE goods SET total=total-1 WHERE id=1";
        $pdo->query($update_sql);
    }
    $pdo = null;

} catch (PDOException $e) {
    die ("Error!: " . $e->getMessage() . "<br/>");
}

//默认这个不是长连接,如果需要数据库长连接,需要最后加一个参数:array(PDO::ATTR_PERSISTENT => true) 变成这样:
$db = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));


三、ab.exe工具进行高并发测试


命令:

ab -n 500 -c 500 http://web.whm.com/concurrency.php

1.png

压力测试:

压力测试是一种基本的质量保证行为,它是每个重要软件测试工作的一部分。压力测试的基本思路很简单:不是在常规条件下运行手动或自动测试,而是在计算机数量较少或系统资源匮乏的条件下运行测试。通常要进行压力测试的资源包括内部内存、CPU 可用性、磁盘空间和网络带宽等。一般用并发来做压力测试。

压力测试工具:webbench,ApacheBench(如上,简称ab)等


四、运行后的结果


2.png

商品数量出现了负数,显然,在高并发的情况下,代码这样写是有问题的