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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 9327|回复: 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://请求的脚本
复制代码
6 _3 d0 L1 d4 [5 p
Mysql中的锁语法:+ w2 G" z' W( {( g& c8 X  z
LOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE .................. 【锁表】7 ]# e7 p. U% @6 v
UNLOCK TABLES  【释放表】
Read:读锁|共享锁 : 所有的客户端只能读这个表不能写这个表2 ]: q& a* [; p6 r4 V
Write:写锁|排它锁: 所有当前锁定客户端可以操作这个表,其他客户端只能阻塞
! \5 ?8 b  b  g' l% z- X注意:在锁表的过程中只能操作被锁定的表,如果要操作其他表,必须把所有要操作的表都锁定起来!
PHP中的文件锁 :2 O+ v+ q4 H3 e5 g4 j
文件锁的文件与表有什么关系?:一点关系也没有,与令牌相似,谁拿到谁操作。所以表根本没锁。( z  G2 k' @7 F! |
测试时,有个文件就行,叫什么名无所谓
总结:
+ f9 D9 p% O+ a7 }% p' O项目中应该只使用PHP中的文件锁,尽量避免锁表,因为如果表被锁定了,那么整个网站中所有和这个表相关的功能都被拖慢了(例如:前台很多用户一直下订单,商品表mysql锁表,其他与商品表相关的操作一直处于阻塞状态【读不出来商品表】,因为一个功能把整个网站速度拖慢)。
比如在一个O2O外卖项目中,中午12-2点,晚上6点都是订单高并发时,这种情况下,MySQL锁显然是不考虑的,用户体验太差。其实根据实际的需求,外卖可以不用设计库存量的,当然除了秒杀活动模块还是需要php文件锁的。
应用场景:
: X; X) T% G' C1. 高并发下单时,减库存量时要加锁
# ^4 q8 a! W4 K( n2. 高并发抢单、抢票时要使用
Mysql锁示例:
  1.    /*( \6 Y- G. p- B8 w8 w
  2.     模拟秒杀活动-- 商品100件1 g9 p- j7 P% ]# Y  m
  3.     CREATE TABLE ta. L3 y' I1 E) ~3 D
  4.     (0 ]& I* R0 _9 Z( ]4 [" G
  5.         id int comment '模拟100件活动商品的数量'
    ( b. A! D' U; s8 r
  6.     );
    . R3 I7 n) g6 i; u
  7.     INSERT INTO ta VALUES(100);
    : c1 i2 `1 L% S" @9 ]3 V7 Q  E6 X
  8.     模仿:以10的并发量访问这个脚本!    使用apache自带的ab.exe软件
    # N3 G7 ~$ Y/ ~
  9.      */
    ' v8 y# t, D! Y  u8 b
  10.     6 c% }* H  E5 A5 o4 o
  11.     // 关闭错误报告
    - d; o. D3 S* w! p, I( q
  12.      error_reporting(0);
    ' C. b6 W" |7 ?' X& t+ A1 S3 A. L! v
  13. ! h9 W% s. f. f( a6 P2 C* r1 `( A
  14.      $dbhost = 'localhost:3306';  // mysql服务器主机地址
    ; [0 ]) @9 r2 m+ K# y
  15.     $dbuser = 'root';            // mysql用户名
    3 d6 }+ H" u2 @  T+ m. C& g' J
  16.     $dbpass = 'root';          // mysql用户名密码
    , u% D: k& r4 h0 N$ |: {! c+ r+ Y; ]
  17.     $conn = mysqli_connect($dbhost, $dbuser, $dbpass);
    6 f' ~1 \+ `; o5 v/ y# ?. z0 k" k
  18.     if(! $conn )
    1 o) a8 z3 t- y
  19.     {4 Y% O# n9 p9 K# y5 n0 p4 p' _" r
  20.         die('连接失败: ' . mysqli_error($conn));9 d# D! o; t; A* F% y: d  A- h; B2 ?
  21.     }- v' ?3 s3 E% z3 K, l" |
  22.     // 设置编码,防止中文乱码1 c0 x5 I# q' B: E; H* n
  23.     mysqli_query($conn , "set names utf8");$ G9 t) o# H7 b; R; `* N' [
  24.     mysqli_select_db( $conn, 'temp' );
    ( J2 s7 L1 \. J% F
  25. 8 I% @3 b, r$ X) f
  26.     # mysql 锁 4 q, {. G3 H. s1 I8 o4 v
  27.     mysqli_query($conn , 'LOCK TABLE a WRITE');// 只有一个客户端可以锁定表,其他客户端阻塞在这 " h9 ^# h- G- h) ?- K1 X
  28.     $rs = mysqli_query($conn , 'SELECT id FROM a'); : j) ^8 A; e' A5 \- S, e
  29.     $id = mysqli_result($rs, 0, 0); , k3 c( T' i( A
  30.     if($id > 0)
    , [& R4 i6 y* j4 x- S3 H  R" u, i
  31.     { / C$ j/ T* a: ]+ y0 }
  32.         --$id; 9 ?! p6 _/ S" z% Y3 v8 W6 L
  33.         mysqli_query($conn , 'UPDATE a SET id='.$id);
    , L1 B2 [& ?, O( z4 B
  34.     }
    " V# f2 t2 T3 h$ W0 S$ v7 ^

  35. , z; Z7 _, \6 G* D
  36.     # mysql 解锁 : k% f2 L9 L% y* g2 a
  37.     mysqli_query($conn , 'UNLOCK TABLES');
    ( _1 j' A5 [/ U& }( ^
  38.     //查询解锁后的id值; b7 k1 ?8 o" G# h7 Z
  39.     // $res = mysqli_query($conn , 'SELECT id FROM ta');
    & V# e8 D6 H! ~  ^9 C+ u& q& a; G
  40.     // while($row = mysqli_fetch_assoc($res))( g" N/ h" T  U" h! D/ A0 t
  41.     // {& [6 [/ \# W; C' H
  42.     //     $id = $row['id'];2 E7 o# I+ |* ^6 Z6 Y
  43.     // }) ~2 M  j5 F8 a0 h- m
  44.     // echo $id;
复制代码

0 [, P' u! O- N3 N, B2 H5 I  z; c/ }& ?- @+ a; @

* H( y# C& x" H% R
PHP文件锁示例:
  1. /*
    / t* \3 x/ F* v8 T8 ~4 y$ I
  2.     模拟秒杀活动-- 商品100件6 b& L* \0 ?: T- ~
  3.     CREATE TABLE ta2 h5 c7 b) P  i" O; M) G
  4.     (* b: v4 r' U0 W& D; A: A' N
  5.         id int comment '模拟100件活动商品的数量'
    / _/ Z7 Y8 v9 m  ?- e
  6.     );
    ) Z" l  W4 T: m3 `
  7.     INSERT INTO ta VALUES(100);
    * V6 a- @1 N' m+ C+ I( g
  8.     模仿:以10的并发量访问这个脚本!    使用apache自带的ab.exe软件. y. {5 `. i0 R" g/ V  A' [
  9.      */ 0 c) w1 V( S# z2 ^% L; L2 q% _
  10.    
    : {1 S4 J7 O; A) n0 U
  11.     // 关闭错误报告( }9 c: C4 E+ P& ^# T: l
  12.      error_reporting(0); + _2 A" T7 ]0 O3 n

  13. 4 e9 R* Y8 q8 r0 _
  14.      $dbhost = 'localhost:3306';  // mysql服务器主机地址6 d: c" q4 T0 C; a& J8 ^
  15.     $dbuser = 'root';            // mysql用户名
    - v; H7 u: F+ l
  16.     $dbpass = 'root';          // mysql用户名密码3 a' o+ |1 P' ?: ]
  17.     $conn = mysqli_connect($dbhost, $dbuser, $dbpass);5 ]  K9 d0 V" s- C% ]% P$ Y& P
  18.     if(! $conn )
    # w+ h; h( T1 ]( c+ v+ W8 W
  19.     {
    : j& l; J  g' k( [5 e% K, d9 |
  20.         die('连接失败: ' . mysqli_error($conn));
    $ V. X3 W6 u5 Z9 m. |; u3 U" c
  21.     }
    / Z9 {9 Z$ m- }, {( D8 B9 b1 r7 d
  22.     // 设置编码,防止中文乱码
    " f& G+ V: t  _4 q
  23.     mysqli_query($conn , "set names utf8");
    * g* R# |% g7 j% q/ o3 v" s
  24.     mysqli_select_db( $conn, 'temp' );
    2 x! K& L! ^& n: `5 j: q5 n1 q

  25. + ^! N/ h4 z4 ]" x0 T+ \
  26.     # php中的文件锁 + G7 b! p" b3 i" p) }
  27.     $fp = fopen('./a.lock', 'r'); // php的文件锁和表没关系,随便一个文件即可
    ; F/ b- E, b! S! ?& l: R2 O
  28.     flock($fp, LOCK_EX);// 排他锁
    4 N$ ?7 t& s! X2 H; e; N
  29. ) I" e& B- n/ Y1 T" j- u+ l" D8 V
  30.     $retval = mysqli_query($conn ,'SELECT id FROM ta'); $ `( x1 ^, f- }$ E$ s* @% O
  31.     while($row = mysqli_fetch_assoc($retval))
    - S. A% X: E( ^( d. [+ h, H$ ~& v
  32.     {
    ! x) f- G9 m, @: ]# y
  33.         $id =  $row['id'];
    + e& d+ Z2 z3 H. s" |# b+ c. u
  34.     }
    ' @: g( @) \8 f6 U! \/ h. k  k: |  r
  35.    
    / [0 s/ W# K5 E; e2 E: h* i
  36.     if($id > 0)
    ; A* K" a3 U6 |% l; r
  37.     { - [, c0 G5 w6 t) R
  38.         --$id;
    8 z- z1 V# R0 ?4 ^6 \
  39.         mysqli_query($conn ,'UPDATE ta SET id='.$id);
    0 J& E  N: R0 k: u, Z, J* p
  40.     }
      t3 a9 }/ n0 \1 o7 b* ~/ g
  41.     # php的文件锁,释放锁 & l, w. m' R) I+ Q9 i7 o
  42.     flock($fp, LOCK_UN);
    9 Y" t0 c6 H+ Z; V% Q" d" d" u# t# @
  43.     fclose($fp);% \- Y# C  D# W& Z0 g" t) ~2 ^+ c

  44. 9 c& v1 R* P5 l
  45.     // $res = mysqli_query($conn , 'SELECT id FROM ta');
    6 P: D. C" J4 ~$ ~, o
  46.     // while($row = mysqli_fetch_assoc($res))
    9 \1 m1 F# M4 d$ v
  47.     // {
    6 z9 }' ]$ E) X/ v6 f, Z8 z
  48.     //     $id = $row['id'];* d+ W. f0 n3 C: N$ B- X
  49.     // }' q/ F# Z2 Z. q* G, x5 h1 w  i
  50.     // echo $id;
复制代码
) Z) D: d4 o; n7 E. p
& S- L# B& ]; S4 k% a
抢券活动实例:
  1. public function envelopeSnatching(){
    % P1 d$ V( x8 i) b6 P2 q3 p! g2 f
  2.         $lingqu = $_POST['type'];. w' {" ]! w4 n; U. t9 m% p
  3.         $uid=session('u_id');//用户id4 A3 s. c5 ^& l1 F+ x
  4.         if(!$uid){. p$ p; X3 }) r, |+ ]
  5.             $data['msg']='您没登录,请先登录!';% X. ]2 Y9 C+ d8 w6 u6 i0 i
  6.         }else if(date('Y-m-d') != '2017-12-12'){& i# d, X5 S" f- U' F% p1 g
  7.             $data['msg']='不在活动时间内!';
    / d# n. K4 @3 x+ s
  8.         }else{
    ' Y' t9 ?6 V% c
  9.             $hours=date('H');//当前小时数1 E8 n; b. A" o
  10.             if($hours > '09' || $hours > '17'){1 V: J* z$ R2 Y
  11. , P! M) Q5 _" S0 G7 F
  12.                 if($lingqu == 1 || $lingqu ==2){//点击10点的  C; i- V2 B. ?. [2 {
  13.                     if($lingqu == 1){7 [$ {  b/ x2 D9 U" y0 H/ b, j
  14.                         $is_lingqu=M('active_log')->field('id')->where(array('num_id'=>1,'uid'=>$uid))->find();//判断是否领取过9 J6 j- d' D9 i
  15.                         if($hours > '09'){  l! p* W8 m/ o8 ^8 }+ s. B  b) Z
  16.                             $num=mt_rand(25,28);//优惠券金额& m, E* {" H0 R, ^( S5 u
  17.                             $id=1;
    8 _; D0 C8 T' H
  18.                         }
    ; G0 @3 f0 C! m2 m0 c# e
  19.                     }else if($lingqu == 2){
    % H# z5 W5 c5 Q8 B) E
  20.                         $is_lingqu=M('active_log')->field('id')->where(array('num_id'=>2,'uid'=>$uid))->find();
    2 s8 t0 Y' M1 A7 N7 n- t
  21.                         if($hours > '17'){3 i# M/ s; C. R5 }  H
  22.                             $num=mt_rand(50,55);//优惠券金额) e, V% I, c8 Y; U
  23.                             $id=2;" I6 E6 P% `8 L9 j
  24.                         }8 v) ]6 s. k  x6 G( r% s7 A5 S' n
  25.                     }/ U8 G0 h2 W6 H/ R7 R- K1 W
  26.                     if(!$id){! p* l+ w8 M1 c; |( R
  27.                         $data['msg']='时间还没到,晚点再来吧。';
    5 W" L, M' {- z, q2 n
  28.                     }else{$ }$ k3 f  G3 ^2 U1 x
  29.                         if($is_lingqu){0 v5 m% L; S0 W& I" X
  30.                             $data['msg']='你已经领取过了,留点给别人吧!';
    7 m7 P% }5 v" |7 z
  31.                         }else{
    $ P8 J* [. P/ P. l2 z: k
  32.                             //锁表+ v9 B8 }9 C! }* w: d+ \2 i2 x7 a. [3 K
  33.                             M()->execute('LOCK TABLE active_num WRITE,active_log WRITE');+ y& \+ B. Q" o: I! K
  34.                             $active=M('active_num')->where(array('id'=>$id))->find();/ b0 p9 q: f1 d- b# v6 b
  35.                             if($active > 0){0 ^1 [; u1 q  K" h3 A9 O
  36.                                 //开启事务
    & X. t) [& a9 d5 w
  37.                                 M()->execute('start transaction');
    0 A2 T. p; U% c
  38.                                 $save=M('active_num')->save(array('id'=>$id,'num'=>$active['num']-1));! M% Z2 u% x% h  U% b" i& X
  39.                                 $add=M('active_log')->add(array('uid'=>$uid,'money'=>$num,'num_id'=>$id,'addtime'=>time()));
    ; \6 w0 Y- S# J( e; _" }
  40.                                 $members_preferential    =    M('members_preferential');
    5 A' e( e. _, P7 z- r& {  k
  41.                                 //对应投资金额,2 q, k2 l2 p9 |3 L- d( k) a" ~
  42.                                 $key=array_search($num,array_reverse(C('PREFERENTIAL_JL'),true));
    % c5 l5 l8 M: x! v! |: i; {
  43.                                 $PREFERENTIAL_ENDDAY=C('PREFERENTIAL_ENDDAY');
    2 U* ^% q6 v: H. z
  44.                                 $endtime=strtotime("+{$PREFERENTIAL_ENDDAY}day");//过期时间: Q- n: b! H7 C3 A! L
  45.                                 $add2=$members_preferential->add(array('uid'=>$uid,'type'=>$key,'endtime'=>$endtime));//添加优惠券/ [; w1 s1 Z$ E) m" K. f
  46.                                 if($save && $add && $add2){5 L* R& D/ Q3 F. B) N0 s
  47.                                     //事务提交
    - s0 V5 H1 r$ R. G) L8 h7 i
  48.                                     M()->execute('commit');: L5 m" m( _0 m6 j
  49.                                     $data['msg']='恭喜你领取了'.$num.'元优惠券';
    % Z3 A6 T. P# U7 G6 g1 A% k
  50.                                 }else{
    % [" M0 M9 a6 u( h/ J
  51.                                     //回滚7 u: t/ M& \3 q  p' y1 B
  52.                                     M()->execute('rollback');. v0 K7 [8 w4 R0 w
  53.                                     $data['msg']='未知错误!';
    . m# W1 ]) I) U5 \& {
  54.                                 }" J( Z  K6 E' H6 R+ Y, B  M
  55.                             }else{
    9 @0 T4 h' u& R
  56.                                 $data['msg']='红包已领完,你来晚了!';  S8 a1 A. y- S& c$ S. m9 Q
  57.                             }
    1 x, H* W( x3 Z% Z8 ~! X& u
  58.                             M()->execute('UNLOCK TABLES');
    3 f2 @. r' ~' P7 X: Y, ~
  59.                         }
    * I4 M: N; L, d( Y( K( ~- t5 a
  60.                     }
    # ~' W3 F9 x" [
  61.                 }else{
    # U0 J! }- C9 Q$ d6 t
  62.                     $data['msg']='非法操作!';/ s5 {9 Z* N  ?# h7 W$ J
  63.                 }' p( u' `" o# ~/ |3 ~" G
  64.             }else{
    ' D( F' r( w; }; j/ o7 W
  65.                 $data['msg']='还没有到活动时间,请晚点再来哟!!';
    0 w  m0 g: \# F  R7 q
  66.             }7 ]% e: z3 ~% w) M9 Y2 B9 `
  67.         }
    , n: I* Q# N/ o
  68.         exit(json_encode($data));
    & W$ U2 d" `& L
  69.     }
复制代码
/ S/ ^' e; I: B" ~+ C8 r7 a

2 j) a% l0 J! }! b% Z$ b
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 07:08 , Processed in 0.053819 second(s), 19 queries .

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