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


Posted in PHP onSeptember 04, 2018

前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题

先看没有利用事务的时候并发的后果

创建库存管理表

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

创建订单管理表

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)

mysql> select * from `order`;
+----+--------+
| id | number |
+----+--------+
| 22 |   10 |
| 23 |   10 |
| 24 |   8 |
| 25 |   8 |
| 26 |   7 |
| 27 |   6 |
| 28 |   4 |
| 29 |   3 |
| 30 |   2 |
| 31 |   2 |
| 32 |   2 |
| 33 |   1 |
+----+--------+
12 rows in set (0.00 sec)

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

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

修改代码如下

$pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456');
$pdo->beginTransaction();//开启事务
$sql="select `number` from storage where id=1 for UPDATE ";//利用for update 开启行锁
$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";
    if($pdo->query($sql))
    {
      $pdo->commit();//提交事务
    }
    else
    {
      $pdo->rollBack();//回滚
    }

  }
  else
  {
    $pdo->rollBack();//回滚
  }
}

查看结果

mysql> select * from storage;
+----+--------+
| id | number |
+----+--------+
| 1 |   0 |
+----+------
--+
1 row in set (0.00 sec)

mysql> select * from `order`;
+----+--------+
| id | number |
+----+--------+
| 1 |   10 |
| 2 |   9 |
| 3 |   8 |
| 4 |   7 |
| 5 |   6 |
| 6 |   5 |
| 7 |   4 |
| 8 |   3 |
| 9 |   2 |
| 10 |   1 |
+----+--------+
10 rows in set (0.00 sec)

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP 事务处理数据实现代码
May 13 PHP
PHP分多步骤填写发布信息的简单方法实例代码
Sep 23 PHP
php获取网页标题和内容函数(不包含html标签)
Feb 03 PHP
PHP判断是否有Get参数的方法
May 05 PHP
PHP中使用CURL获取页面title例子
Jan 07 PHP
php抽象类使用要点与注意事项分析
Feb 09 PHP
php实现httpRequest的方法
Mar 13 PHP
php从字符串创建函数的方法
Mar 16 PHP
微信公众平台DEMO(PHP)
May 04 PHP
Laravel SQL语句记录方式(推荐)
May 26 PHP
PHP jQuery+Ajax结合写批量删除功能
May 19 PHP
PHP随机生成中文段落示例【测试网站内容时使用】
Apr 26 PHP
TP5(thinkPHP5)框架基于ajax与后台数据交互操作简单示例
Sep 03 #PHP
PHP实现的AES双向加密解密功能示例【128位】
Sep 03 #PHP
PHP实现的日历功能示例
Sep 01 #PHP
thinkPHP5框架分页样式类完整示例
Sep 01 #PHP
php操作mongodb封装类与用法实例
Sep 01 #PHP
thinkphp集成前端脚手架Vue-cli的教程图解
Aug 30 #PHP
Django中通过定时任务触发页面静态化的处理方式
Aug 29 #PHP
You might like
php实现的漂亮分页方法
2014/04/17 PHP
thinkPHP删除前弹出确认框的简单实现方法
2016/05/16 PHP
PHP实现正则匹配所有括号中的内容
2018/06/22 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
JavaScript 数组的 uniq 方法
2008/01/23 Javascript
一个用javascript写的select支持上下键、首字母筛选以及回车取值的功能
2009/09/09 Javascript
Node.js的包详细介绍
2015/01/14 Javascript
angularjs学习笔记之完整的项目结构
2015/09/26 Javascript
JavaScript设计模式经典之工厂模式
2016/02/24 Javascript
微信js-sdk界面操作接口用法示例
2016/10/12 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
解决微信小程序调用moveToLocation失效问题【超简单】
2019/04/12 Javascript
解决vue-router 二级导航默认选中某一选项的问题
2019/11/01 Javascript
ES6 Object.assign()的用法及其使用
2020/01/18 Javascript
原生js实现日历效果
2020/03/02 Javascript
vue切换菜单取消未完成接口请求的案例
2020/11/13 Javascript
wxPython中文教程入门实例
2014/06/09 Python
编写Python CGI脚本的教程
2015/06/29 Python
python3.7实现云之讯、聚合短信平台的短信发送功能
2019/09/26 Python
Python如何使用内置库matplotlib绘制折线图
2020/02/24 Python
pycharm实现print输出保存到txt文件
2020/06/01 Python
利用Python将图片中扭曲矩形的复原
2020/09/07 Python
如何用Matlab和Python读取Netcdf文件
2021/02/19 Python
CSS3的Border-radius轻松制作圆角
2012/12/24 HTML / CSS
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
计算机通信工程专业毕业生推荐信
2013/12/24 职场文书
会走路的树教学反思
2014/02/20 职场文书
奥巴马获胜演讲稿
2014/05/15 职场文书
爱与责任演讲稿
2014/05/20 职场文书
竞赛口号大全
2014/06/16 职场文书
授权委托书范文
2014/07/31 职场文书
学校后勤工作总结2015
2015/05/15 职场文书
政协工作总结2015
2015/05/20 职场文书
Nginx 负载均衡是什么以及该如何配置
2021/03/31 Servers
Pytorch 中net.train 和 net.eval的使用说明
2021/05/22 Python
【海涛DOTA解说】EVE女子战队独家录像加ZSMJ神牛两连发
2022/04/01 DOTA