当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP利用Mysql锁解决高并发的方法

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-27 15:17:19 浏览: 评论:0 

这篇文章主要介绍了PHP利用Mysql锁解决高并发的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考,一起跟随小编过来看看吧。

前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题,先看没有利用事务的时候并发的后果。

创建库存管理表

  1. CREATE TABLE `storage` ( 
  2.  `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  3.  `number` int(11) DEFAULT NULL
  4.  PRIMARY KEY (`id`) 
  5. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 

创建订单管理表

  1. CREATE TABLE `order` ( 
  2.  `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  3.  `number` int(11) DEFAULT NULL
  4.  PRIMARY KEY (`id`) 
  5. ) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1 

测试代码

  1. $pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456'); 
  2. $sql="select `number` from storage where id=1 limit 1"
  3. $res = $pdo->query($sql)->fetch(); 
  4. $number = $res['number']; 
  5.  
  6. if($number>0) 
  7.   $sql ="insert into `order` VALUES (null,$number)"
  8.     
  9.   $order_id = $pdo->query($sql); 
  10.   if($order_id
  11.   { 
  12.  
  13.     $sql="update storage set `number`=`number`-1 WHERE id=1"
  14.     $pdo->query($sql); 
  15.   } 

我们预置库存是十个,然后执行ab测试查看结果

  1. mysql> select * from storage 
  2.   -> ; 
  3. +----+--------+ 
  4. | id | number | 
  5. +----+--------+ 
  6. | 1 |   -2 | 
  7. +----+--------+ 
  8. 1 row in set (0.00 sec) 
  9.  
  10. mysql> select * from `order`; 
  11. +----+--------+ 
  12. | id | number | 
  13. +----+--------+ 
  14. | 22 |   10 | 
  15. | 23 |   10 | 
  16. | 24 |   8 | 
  17. | 25 |   8 | 
  18. | 26 |   7 | 
  19. | 27 |   6 | 
  20. | 28 |   4 | 
  21. | 29 |   3 | 
  22. | 30 |   2 | 
  23. | 31 |   2 | 
  24. | 32 |   2 | 
  25. | 33 |   1 | 
  26. +----+--------+ 
  27. 12 rows in set (0.00 sec) 

得到了订单共有12个,而库存表的库存也减到了-2,这显然不符合实际逻辑的;

下面我们来看利用数据库行锁来解决这个问题

修改代码如下

  1. $pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456'); 
  2. $pdo->beginTransaction();//开启事务 
  3. $sql="select `number` from storage where id=1 for UPDATE ";//利用for update 开启行锁 
  4. $res = $pdo->query($sql)->fetch(); 
  5. $number = $res['number']; 
  6.  
  7. if($number>0) 
  8.   $sql ="insert into `order` VALUES (null,$number)"
  9.  
  10.   $order_id = $pdo->query($sql); 
  11.   if($order_id
  12.   { 
  13.  
  14.     $sql="update storage set `number`=`number`-1 WHERE id=1"
  15.     if($pdo->query($sql)) 
  16.     { 
  17.       $pdo->commit();//提交事务 
  18.     } 
  19.     else 
  20.     { 
  21.       $pdo->rollBack();//回滚 
  22.     } 
  23.  
  24.   } 
  25.   else 
  26.   { 
  27.     $pdo->rollBack();//回滚 
  28.   } 

查看结果

  1. mysql> select * from storage; 
  2. +----+--------+ 
  3. | id | number | 
  4. +----+--------+ 
  5. | 1 |   0 | 
  6. +----+------ 
  7. --+ 
  8. 1 row in set (0.00 sec) 
  9.  
  10. mysql> select * from `order`; 
  11. +----+--------+ 
  12. | id | number | 
  13. +----+--------+ 
  14. | 1 |   10 | 
  15. | 2 |   9 | 
  16. | 3 |   8 | 
  17. | 4 |   7 | 
  18. | 5 |   6 | 
  19. | 6 |   5 | 
  20. | 7 |   4 | 
  21. | 8 |   3 | 
  22. | 9 |   2 | 
  23. | 10 |   1 | 
  24. +----+--------+ 
  25. 10 rows in set (0.00 sec) 

很明显在利用了mysql锁之后,对库存进行了有效的控制,很好的解决了第一段代码里面,因为并发引起的一些逻辑性的问题。

Tags: Mysql锁 Mysql高并发

分享到: