MySQL锁机制和PHP锁机制
2020-08-07 本文已影响0人
Mracale
模拟准备--如何模拟高并发访问一个脚本:
apache安装文件的bin/ab.exe可以模拟并发量 -c 模拟多少并发量 -n 一共请求多少次 http://请求的脚本例如:
cmd: apache安装路径/bin/ab.exe -c 10 -n 10 http://my.test.com/miao.php
或者可以使用apache jmeter 、loaderunner之类的进行压测
MYSQL中的锁:
语法 :
LOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE ..................
【锁表】UNLOCK TABLES
【释放表】
Read:读锁|共享锁 : 所有的客户端只能读这个表不能写这个表
Write:写锁|排它锁: 所有当前锁定客户端可以操作这个表,其他客户端只能阻塞
注意:在锁表的过程中只能操作被锁定的表,如果要操作其他表,必须把所有要操作的表都锁定起来!
PHP中的文件锁 (锁的是文件,不是表)文件锁的文件与表有什么关系?:一点关系也没有,与令牌相似,谁拿到谁操作。所以表根本没锁。测试时,有个文件就行,叫什么名无所谓
总结:项目中应该只使用PHP中的文件锁,尽量避免锁表,因为如果表被锁定了,那么整个网站中所有和这个表相关的功能都被拖慢了(例如:前台很多用户一直下订单,商品表mysql锁表,其他与商品表相关的操作一直处于阻塞状态【读不出来商品表】,因为一个功能把整个网站速度拖慢)。
应用场景:
高并发下单时,减库存量时要加锁
高并发抢单、抢票时要使用
MySQL锁示例代码:
<?php
/**
模拟秒杀活动-- 商品100件
CREATE TABLE a
(
id int comment '模拟100件活动商品的数量'
);
INSERT INTO a VALUES(100);
模仿:以10的并发量访问这个脚本! 使用apache自带的ab.exe软件
*/
error_reporting(0);
error_reporting(0);
// 假定数据库用户名:root,密码:456852,数据库:test
$con=mysqli_connect("localhost","root","456852","test");
if (mysqli_connect_errno($con)){
echo "连接 MySQL 失败: " . mysqli_connect_error();
}
# mysql 锁
mysqli_query($con,'LOCK TABLE a WRITE');// 只有一个客户端可以锁定表,其他客户端阻塞在这
$rs = mysqli_query($con,'SELECT id FROM a');
$data = $rs->fetch_assoc();
$id = 0;
if (!empty($data)) {
$id = $data['id'];
}
if($id > 0){
--$id;
mysqli_query($con,'UPDATE a SET id='.$id);
}
//mysql 解锁
mysqli_query($con,'UNLOCK TABLES');
PHP锁示例代码:
<?php
/**
模拟秒杀活动-- 商品10件
CREATE TABLE a
(
id int comment '模拟10件活动商品的数量'
);
INSERT INTO a VALUES(100);
模仿:以10的并发量访问这个脚本! 使用apache自带的ab.exe软件
*/
error_reporting(0);
// 假定数据库用户名:root,密码:456852,数据库:test
$con=mysqli_connect("localhost","root","456852","test");
if (mysqli_connect_errno($con)){
echo "连接 MySQL 失败: " . mysqli_connect_error();
}
/**
php中的文件锁
php的文件锁和表没关系,随便一个文件即可,目的只是让一个请求进来
**/
$fp = fopen('./a.lock', 'r');
flock($fp, LOCK_EX);// 排他锁
$rs = mysqli_query($con,'SELECT id FROM a');
$data = $rs->fetch_assoc();
$id = 0;
if (!empty($data)) {
$id = $data['id'];
}
if($id > 0){
--$id;
mysqli_query($con,'UPDATE a SET id='.$id);
}
# php的文件锁,释放锁
flock($fp, LOCK_UN);
fclose($fp);
?>