您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 4005|回复: 0
打印 上一主题 下一主题

[php学习资料] MySQL(表锁)、PHP(文件锁)锁机制及应用场景

[复制链接]
跳转到指定楼层
楼主
发表于 2022-3-17 15:53:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
模拟高并发访问一个脚本:apache安装文件的bin/ab.exe可以模拟并发量
  1. C:\phpStudy\Apache\bin>ab.exe -c 10 -n 10 http://localhost/try.php   // -c 模拟多少并发量 -n 一共请求多少次 http://请求的脚本
复制代码

1 {5 u2 s* L5 V6 q4 e6 U
Mysql中的锁语法:
% X- l7 P' c- d& ~2 eLOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE .................. 【锁表】
0 M$ J( d( K! ]( _% DUNLOCK TABLES  【释放表】
Read:读锁|共享锁 : 所有的客户端只能读这个表不能写这个表
- `) m: c# t5 [" iWrite:写锁|排它锁: 所有当前锁定客户端可以操作这个表,其他客户端只能阻塞
5 N- h1 f) ?' z2 M注意:在锁表的过程中只能操作被锁定的表,如果要操作其他表,必须把所有要操作的表都锁定起来!
PHP中的文件锁 :
  b6 i1 c! f0 e9 o文件锁的文件与表有什么关系?:一点关系也没有,与令牌相似,谁拿到谁操作。所以表根本没锁。
4 ^; Q/ h  R2 r4 K9 F测试时,有个文件就行,叫什么名无所谓
总结:4 ?8 Q: u1 f8 g+ v" C! |
项目中应该只使用PHP中的文件锁,尽量避免锁表,因为如果表被锁定了,那么整个网站中所有和这个表相关的功能都被拖慢了(例如:前台很多用户一直下订单,商品表mysql锁表,其他与商品表相关的操作一直处于阻塞状态【读不出来商品表】,因为一个功能把整个网站速度拖慢)。
比如在一个O2O外卖项目中,中午12-2点,晚上6点都是订单高并发时,这种情况下,MySQL锁显然是不考虑的,用户体验太差。其实根据实际的需求,外卖可以不用设计库存量的,当然除了秒杀活动模块还是需要php文件锁的。
应用场景:& f/ n) b& T5 Y  i- f$ j
1. 高并发下单时,减库存量时要加锁. e- |- k: p# s6 A4 P* m
2. 高并发抢单、抢票时要使用
Mysql锁示例:
  1.    /*9 ]# D3 `/ X1 ^: A
  2.     模拟秒杀活动-- 商品100件
    ! D/ s7 O; m1 y" X2 M, i- z
  3.     CREATE TABLE ta
    2 b* |$ ^* D) S& o- k1 }
  4.     (2 R, T9 a, I: l6 Z% h
  5.         id int comment '模拟100件活动商品的数量'
    8 |2 k0 O" D: V) H7 y' ~5 Z& Y
  6.     );$ l& S  y6 F4 S# g0 Q
  7.     INSERT INTO ta VALUES(100);
    # c% C, f1 ~! B# h4 _7 n6 N
  8.     模仿:以10的并发量访问这个脚本!    使用apache自带的ab.exe软件
    - }" V: Q1 Y+ v: e- J
  9.      */
    : h! G/ o% T2 S* l6 C& q! A/ u
  10.    
    5 c/ c9 k6 U5 e- l! S
  11.     // 关闭错误报告+ l! x# Q# a9 O& m
  12.      error_reporting(0); 5 ~) a( R7 q% W
  13. 2 z. C( z: I  B: `
  14.      $dbhost = 'localhost:3306';  // mysql服务器主机地址, Q' S/ ]. B: `
  15.     $dbuser = 'root';            // mysql用户名3 `& P& v$ `" H5 G( b
  16.     $dbpass = 'root';          // mysql用户名密码
    ( y8 @2 {  b  {: y
  17.     $conn = mysqli_connect($dbhost, $dbuser, $dbpass);
    ; q, Y8 q, A2 Y& ^
  18.     if(! $conn )
    / U; n: O- a# {# [
  19.     {2 V) t5 D+ o0 _7 K3 L/ \. S
  20.         die('连接失败: ' . mysqli_error($conn));8 E1 V9 C+ c, p5 T" `
  21.     }8 P8 F% H! y; F$ Y9 v  B
  22.     // 设置编码,防止中文乱码
      w7 T- D( [: P
  23.     mysqli_query($conn , "set names utf8");4 Z# P. P- h  ^6 ^& c: R- W
  24.     mysqli_select_db( $conn, 'temp' );
    ; U3 e/ n+ m8 d' W; Z) m

  25. . J* T: i/ Y1 I5 J0 U7 l  [
  26.     # mysql 锁 2 b! D$ [4 B: n
  27.     mysqli_query($conn , 'LOCK TABLE a WRITE');// 只有一个客户端可以锁定表,其他客户端阻塞在这 5 }9 _( z3 \7 X  J
  28.     $rs = mysqli_query($conn , 'SELECT id FROM a');
    4 x' C5 e2 e2 \- J, i
  29.     $id = mysqli_result($rs, 0, 0); ; ?! g4 {, l- `- v/ a- z$ X
  30.     if($id > 0)
    2 w2 w7 U& p( n0 J7 b2 r
  31.     {
    / n* C# T2 ~% O- E% C+ L) S0 U! Q9 x
  32.         --$id;
    ; u, ]9 {4 [' @0 w& z
  33.         mysqli_query($conn , 'UPDATE a SET id='.$id); 0 |, U9 \! Z' P6 b
  34.     }
    : F$ A* W* ^. k# X7 q* R6 ]" I3 G

  35. 4 o1 ]" Z! u; @, [# E
  36.     # mysql 解锁
    : n( L$ ~1 a% M
  37.     mysqli_query($conn , 'UNLOCK TABLES');
    : d. r" a" s! v, i: V; d7 E
  38.     //查询解锁后的id值1 _8 j) H# F2 d( s
  39.     // $res = mysqli_query($conn , 'SELECT id FROM ta');$ U6 V9 o* C. s+ W
  40.     // while($row = mysqli_fetch_assoc($res))
    " B9 J  c3 i1 T- U) Y* r$ S! {
  41.     // {) w+ L2 R0 ?$ C9 g2 _* F
  42.     //     $id = $row['id'];, E4 \. p# k; L7 a
  43.     // }3 B  b( j9 t* @  n. ]
  44.     // echo $id;
复制代码
+ U# S1 G6 o7 U

( t% \3 n) A9 V. h- Q

6 N2 `1 a4 [) j8 V3 T
PHP文件锁示例:
  1. /*
    # X' A, M' c! S/ `. U8 W% M0 l4 s
  2.     模拟秒杀活动-- 商品100件7 Z. f. v  m7 g( q3 z8 h- |. a
  3.     CREATE TABLE ta
    ' q7 s1 Q6 o0 ~6 D& [) E3 z" _
  4.     (
    4 `7 }2 u" W' g# H+ i( U- I
  5.         id int comment '模拟100件活动商品的数量'
    8 y4 |5 }5 N5 K% r& M% M3 _" \
  6.     );
    $ V$ s( B- [2 y: K
  7.     INSERT INTO ta VALUES(100);
    " w: A0 w+ ~2 C- g' k& m
  8.     模仿:以10的并发量访问这个脚本!    使用apache自带的ab.exe软件
    1 b$ M6 {5 @( U9 r
  9.      */
    % H" S- x' W5 n7 ?% f/ m8 @/ c. C
  10.     # }& Q, M3 {* O/ x; t
  11.     // 关闭错误报告/ M) o1 H2 l* @2 c- H% G4 V0 P+ \/ M
  12.      error_reporting(0);
    ! u4 l/ {' y( X$ d

  13. ) W9 }  P. c. p$ [( c1 e* x$ x- V4 R; F
  14.      $dbhost = 'localhost:3306';  // mysql服务器主机地址2 `; s! v  ~, F1 Z
  15.     $dbuser = 'root';            // mysql用户名
    4 G/ Z# U& S; o2 p
  16.     $dbpass = 'root';          // mysql用户名密码2 ]/ j) l1 w  N# ?
  17.     $conn = mysqli_connect($dbhost, $dbuser, $dbpass);
    + f  Z0 `7 U2 ^# h0 {) Q% R' U
  18.     if(! $conn )+ [, p5 Q. f( `, C
  19.     {+ f3 R. R6 G: M. e
  20.         die('连接失败: ' . mysqli_error($conn));6 t+ y: ~7 H$ K( \. c: o2 a
  21.     }- O8 M# c  B! m5 Y/ I8 n) I" G/ O
  22.     // 设置编码,防止中文乱码* S4 n4 k/ e0 L9 D8 K0 r$ i, a3 ~# `
  23.     mysqli_query($conn , "set names utf8");8 K. a8 y/ w+ G0 K: H
  24.     mysqli_select_db( $conn, 'temp' );
    ! P5 X; K* s# b7 e; i# g

  25. / l6 J8 H# p. `% X' |7 D
  26.     # php中的文件锁 $ \$ V0 v; G8 R: a# i# ]& Y
  27.     $fp = fopen('./a.lock', 'r'); // php的文件锁和表没关系,随便一个文件即可
    * ^9 x' u. A6 v( j, h+ P% ]
  28.     flock($fp, LOCK_EX);// 排他锁
    6 G% V# \0 H6 l5 n  Y
  29. " X0 L$ w( \6 O9 D4 K6 Z& T
  30.     $retval = mysqli_query($conn ,'SELECT id FROM ta'); ! p( Q8 E/ \2 [3 Q0 ^/ i3 U
  31.     while($row = mysqli_fetch_assoc($retval))
    / A$ T" ?( s" Q' e$ n
  32.     {, Q+ q" x+ w# r5 s
  33.         $id =  $row['id'];
    / c2 X: ~1 D# H+ S, `2 N- f
  34.     }' V% w7 y% J' h4 w
  35.     " w( z$ [9 v& T1 a& u; a
  36.     if($id > 0) 8 b4 x! P) ~# R% F0 F' N  L5 }- V
  37.     { ( N: M& I2 `. B6 ?+ W( P0 ^
  38.         --$id;
    3 {' o# a9 k% L8 u3 `" \
  39.         mysqli_query($conn ,'UPDATE ta SET id='.$id); " u6 U# R2 \+ b  i
  40.     } & y: U$ x6 c/ p. m2 z5 g0 F
  41.     # php的文件锁,释放锁 6 l- V4 Y& ?( T: B9 r; H4 }( m3 c
  42.     flock($fp, LOCK_UN);
    : O2 ?; q. n5 C3 ~3 d! V
  43.     fclose($fp);( M: Y  e# J. m- I7 L4 d* T$ V
  44. ! \; i! ]7 J9 q4 E
  45.     // $res = mysqli_query($conn , 'SELECT id FROM ta');: H5 p1 w9 M. W8 s; K/ G' K
  46.     // while($row = mysqli_fetch_assoc($res))
    ( w: t3 @- \5 b2 F( d' g3 h; }
  47.     // {
    3 }" e; i+ C2 _5 q
  48.     //     $id = $row['id'];3 u- a# ?# ^- w8 z" }
  49.     // }6 a# p7 X9 X' O" H. `! X2 ]' f/ S
  50.     // echo $id;
复制代码

1 N+ p1 i. A) X* J, Y! j$ W( U! w) Y5 o
抢券活动实例:
  1. public function envelopeSnatching(){6 ~7 j2 t2 G9 G4 u8 @, I" D% b
  2.         $lingqu = $_POST['type'];4 p5 L& `/ e+ A- Z8 I- w
  3.         $uid=session('u_id');//用户id% |3 n2 ?$ [) _5 _- m+ {
  4.         if(!$uid){8 e( X2 r) x5 Q/ I# v
  5.             $data['msg']='您没登录,请先登录!';
    # \$ B% C, i; s( M
  6.         }else if(date('Y-m-d') != '2017-12-12'){+ M3 i) w( A5 k
  7.             $data['msg']='不在活动时间内!';
    5 {3 I6 q3 K4 F0 h. G2 o3 ^( s
  8.         }else{. g  f. b% X" D7 q
  9.             $hours=date('H');//当前小时数$ a+ l, b' x% I* ^# f
  10.             if($hours > '09' || $hours > '17'){
    ' t+ @' Y( |( t# o3 e( Y3 G

  11. 7 e( y1 Q( v. H0 A1 u( H/ _
  12.                 if($lingqu == 1 || $lingqu ==2){//点击10点的$ r; i  x4 S& J. ]' R3 C2 O
  13.                     if($lingqu == 1){
    # ]3 @) X0 c: @$ Q+ ~  g+ d0 x5 t- g
  14.                         $is_lingqu=M('active_log')->field('id')->where(array('num_id'=>1,'uid'=>$uid))->find();//判断是否领取过9 h1 `2 Z& T! L8 k% X( o
  15.                         if($hours > '09'){, E  d" `7 Q* w- r+ ^+ E/ {) ?
  16.                             $num=mt_rand(25,28);//优惠券金额
    ! g. P/ Q: b' Y% x, {8 k
  17.                             $id=1;
    0 u# ]3 m9 H# e. J9 ?
  18.                         }
    * L5 A% o; E7 b- ?! r/ L
  19.                     }else if($lingqu == 2){: X5 \7 f$ U0 V; V1 M7 b
  20.                         $is_lingqu=M('active_log')->field('id')->where(array('num_id'=>2,'uid'=>$uid))->find();2 l4 q+ i) n9 `' Z
  21.                         if($hours > '17'){
    " `% C. u. C+ K2 g
  22.                             $num=mt_rand(50,55);//优惠券金额9 q) _2 f0 W9 P9 w4 V. T
  23.                             $id=2;2 s. P) _( u8 ?# |  D. z& g
  24.                         }
    5 H. v; \& R' U/ f7 }5 h: o
  25.                     }( J- R: N( f. t- }3 R. b
  26.                     if(!$id){8 `2 g) D3 e3 I1 d
  27.                         $data['msg']='时间还没到,晚点再来吧。';3 h$ f: J7 N/ j* z: }6 R
  28.                     }else{5 V. d) u6 q3 N+ g( I
  29.                         if($is_lingqu){" d& p5 n; E2 n: `3 H
  30.                             $data['msg']='你已经领取过了,留点给别人吧!';3 x+ X/ }0 X4 v* \; w! d& N& S6 F
  31.                         }else{
      f5 `; |* w2 G  r
  32.                             //锁表
    & N2 m* m, @% T/ [: a) r" C3 E
  33.                             M()->execute('LOCK TABLE active_num WRITE,active_log WRITE');" W6 [4 {0 C" ^( N# S" a- W8 e( s, o
  34.                             $active=M('active_num')->where(array('id'=>$id))->find();
    - G4 V6 M& s; K. v
  35.                             if($active > 0){
      s* s4 g' d3 Q$ L. E( ]' a
  36.                                 //开启事务+ {% M8 C8 S9 ?. P
  37.                                 M()->execute('start transaction');) H  J$ ]5 D" ^- x. }
  38.                                 $save=M('active_num')->save(array('id'=>$id,'num'=>$active['num']-1));
    5 x; G  X4 O8 Y+ m& |/ P/ Z4 J
  39.                                 $add=M('active_log')->add(array('uid'=>$uid,'money'=>$num,'num_id'=>$id,'addtime'=>time()));# M% T! l: R7 s; {& p' Y6 M, h
  40.                                 $members_preferential    =    M('members_preferential');! o, h# H$ }9 |  J' a
  41.                                 //对应投资金额,
    5 p& x9 _; r, {  T
  42.                                 $key=array_search($num,array_reverse(C('PREFERENTIAL_JL'),true));/ r4 ~% s( `, w
  43.                                 $PREFERENTIAL_ENDDAY=C('PREFERENTIAL_ENDDAY');3 u- G# w$ m4 s6 q& a" {0 I
  44.                                 $endtime=strtotime("+{$PREFERENTIAL_ENDDAY}day");//过期时间
    , S) F" N2 Z# n
  45.                                 $add2=$members_preferential->add(array('uid'=>$uid,'type'=>$key,'endtime'=>$endtime));//添加优惠券
    & i( p, [: o' }1 p$ o% p
  46.                                 if($save && $add && $add2){
    + P5 T3 ~8 k  l9 H; g, @0 }3 ]
  47.                                     //事务提交3 J9 \$ {% M0 W- t  J! I5 H
  48.                                     M()->execute('commit');. M# Z0 |( C' M
  49.                                     $data['msg']='恭喜你领取了'.$num.'元优惠券';
    3 f7 d* y8 Y# R: d
  50.                                 }else{0 i' k' |0 i* ?, W
  51.                                     //回滚
    # E) F+ Z# o! o+ w+ w7 o) E
  52.                                     M()->execute('rollback');& I# C" |- J  s: g! _! J+ i
  53.                                     $data['msg']='未知错误!';
    2 e/ K* w1 x# d3 |  e
  54.                                 }
    ) Y! w$ `( }2 ]' b2 D7 Q7 S4 x
  55.                             }else{
    . d5 c3 S! E/ N# H7 w2 O4 A" u5 J) Y
  56.                                 $data['msg']='红包已领完,你来晚了!';
    7 \5 P) f7 _( u8 K. p
  57.                             }
    : q+ D2 E& W$ X' x
  58.                             M()->execute('UNLOCK TABLES');5 D/ |# ?, p0 a( r2 O
  59.                         }& I) j. a0 I: ?+ e
  60.                     }& p: q4 q. t/ ?+ d% h$ C, I
  61.                 }else{% H* J8 ?$ h( l: V
  62.                     $data['msg']='非法操作!';
    . k$ m! ^, P; I7 e0 M; W
  63.                 }1 j. o( }/ \7 v5 K) G; u/ E
  64.             }else{
    % g% }' ]# b9 m- Z8 t2 x8 @/ ?
  65.                 $data['msg']='还没有到活动时间,请晚点再来哟!!';: N" {1 R& t3 t, s9 G4 ]. }/ e
  66.             }
    % @, ]6 f1 M- x' ?: A
  67.         }; W  Q& P! ]) f0 H) {, {
  68.         exit(json_encode($data));
    - r, V# t# Y: w
  69.     }
复制代码

, x& m' U- i0 U* M) @+ w& b! k2 W2 @
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-19 21:02 , Processed in 0.142773 second(s), 19 queries .

Copyright © 2001-2024 Powered by cncml! X3.2. Theme By cncml!