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);

?>
上一篇下一篇

猜你喜欢

热点阅读