学习目标:

办理类似商城秒杀高并发导致库存变成负数的问题

运用处景

在商城秒杀运用中,高并发时,在没有事务的时候,商品会涌现超卖的情形,即商品的库存涌现负数的情形

php并发锁PHP应用Mysql锁解决高并发问题 jQuery

创建库存管理表

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^)\\\~~~