学习目标:
办理类似商城秒杀高并发导致库存变成负数的问题
运用处景在商城秒杀运用中,高并发时,在没有事务的时候,商品会涌现超卖的情形,即商品的库存涌现负数的情形
创建库存管理表
CREATE TABLE storage (id int(11) unsigned NOT NULL AUTO_INCREMENT,number int(11) DEFAULT NULL,PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8
创建订单管理表
CREATE TABLE order (id int(11) unsigned NOT NULL AUTO_INCREMENT,number int(11) DEFAULT NULL,PRIMARY KEY (id)) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1
不该用事务的时候并发问题测试代码
$pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456');$sql="select `number` from storage where id=1 limit 1";$res = $pdo->query($sql)->fetch();$number = $res['number']; if($number>0){ $sql ="insert into `order` VALUES (null,$number)"; $order_id = $pdo->query($sql); if($order_id) { $sql="update storage set `number`=`number`-1 WHERE id=1"; $pdo->query($sql); }}
我们预置库存是十个,然后实行ab测试查当作果
mysql> select from storage
-> ;+----+--------+| id | number |+----+--------+| 1 | -2 |+----+--------+1 row in set (0.00 sec)
库存数变成了-2,变成了负数,即涌现了超卖征象
利用mysql事务和锁办理并发商品超卖问题代码调度如下
$pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456');$pdo->beginTransaction();//开缘由务$sql="selectnumberfrom storage where id=1 for UPDATE ";//利用for update 开启行锁$res = $pdo->query($sql)->fetch();$number = $res['number'];if($number>0){ $sql ="insert intoorderVALUES (null,$number)"; $order_id = $pdo->query($sql); if($order_id) { $sql="update storage set `number`=`number`-1 WHERE id=1"; if($pdo->query($sql)) { $pdo->commit();//提交事务 } else { $pdo->rollBack();//回滚 } } else { $pdo->rollBack();//回滚 }}
例如ab仿照并发测试之后,查当作果如下:
mysql> select from storage;+----+--------+| id | number |+----+--------+| 1 | 0 |+----+--------+1 row in set (0.00 sec)
利用mysql锁往后,库存数没有变成负数,即没有涌现商品超卖的情形
php7进阶到架构师干系阅读https://www.kancloud.cn/gofor/gofor
末了,欢迎大家留言补充,谈论~~~喜好小编的话,欢迎点赞、收藏和关注哦~~~///(^v^)\\\~~~