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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5738|回复: 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://请求的脚本
复制代码
" u% ?" }" n* v7 D1 r! y8 D
Mysql中的锁语法:0 {5 a) G+ p7 F. t- \$ M
LOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE .................. 【锁表】
$ `  h8 K3 ~& \: h0 M4 A* SUNLOCK TABLES  【释放表】
Read:读锁|共享锁 : 所有的客户端只能读这个表不能写这个表+ `  X1 p# l% w0 X& g4 v& v
Write:写锁|排它锁: 所有当前锁定客户端可以操作这个表,其他客户端只能阻塞
7 P9 m2 n! {" ?: A, ~注意:在锁表的过程中只能操作被锁定的表,如果要操作其他表,必须把所有要操作的表都锁定起来!
PHP中的文件锁 :: g( y$ D2 O7 n/ w$ ^" j- I
文件锁的文件与表有什么关系?:一点关系也没有,与令牌相似,谁拿到谁操作。所以表根本没锁。
: S, J* r. Z$ g5 q4 U+ |0 L) C测试时,有个文件就行,叫什么名无所谓
总结:/ T, a) w, w6 u1 D& D; J
项目中应该只使用PHP中的文件锁,尽量避免锁表,因为如果表被锁定了,那么整个网站中所有和这个表相关的功能都被拖慢了(例如:前台很多用户一直下订单,商品表mysql锁表,其他与商品表相关的操作一直处于阻塞状态【读不出来商品表】,因为一个功能把整个网站速度拖慢)。
比如在一个O2O外卖项目中,中午12-2点,晚上6点都是订单高并发时,这种情况下,MySQL锁显然是不考虑的,用户体验太差。其实根据实际的需求,外卖可以不用设计库存量的,当然除了秒杀活动模块还是需要php文件锁的。
应用场景:
: J' f# {7 z) G) B" J, S1 \- Q* s4 _1. 高并发下单时,减库存量时要加锁7 ?1 N- w. a) [
2. 高并发抢单、抢票时要使用
Mysql锁示例:
  1.    /*
    : ~/ P6 S$ U+ l4 \# R/ d
  2.     模拟秒杀活动-- 商品100件1 f4 S) N8 @" T& ]: d# ]7 ?
  3.     CREATE TABLE ta: q" q$ A& `8 l. @$ @
  4.     (
    1 f3 V. ~" {; a- f
  5.         id int comment '模拟100件活动商品的数量'3 w! d) [' t& w6 n: c& R4 l8 x5 B/ H
  6.     );8 `* u- P6 G6 Q# a
  7.     INSERT INTO ta VALUES(100);
    + D+ S3 D; O7 V8 z" Z7 A# M
  8.     模仿:以10的并发量访问这个脚本!    使用apache自带的ab.exe软件9 q* }7 M4 D  d6 e2 L
  9.      */ + ]. r1 Y: m2 @+ j" \# J6 ]
  10.    
    / s* Y- o& N* j. J5 K
  11.     // 关闭错误报告: y) F8 n7 C! t  w
  12.      error_reporting(0); , u' M, O0 o- i
  13. 2 ^1 T" i0 |% _; I+ q: p
  14.      $dbhost = 'localhost:3306';  // mysql服务器主机地址7 F. U% }# u4 [" C8 o4 E& _- W
  15.     $dbuser = 'root';            // mysql用户名8 }$ e' `" _3 z4 v/ i
  16.     $dbpass = 'root';          // mysql用户名密码
    ( T# G6 |. P, }( h& E! ?) w. B
  17.     $conn = mysqli_connect($dbhost, $dbuser, $dbpass);
    % p0 w* r6 i4 }5 k- ]+ Z0 I* [
  18.     if(! $conn )
    0 y- c# R  D8 f# ~0 g# u/ I% g
  19.     {$ G0 r. d) Q) C
  20.         die('连接失败: ' . mysqli_error($conn));+ M5 D; z' m% X1 T4 B) `
  21.     }
    : j3 F8 |4 r; W9 |
  22.     // 设置编码,防止中文乱码
      W9 v$ E1 @6 e9 X
  23.     mysqli_query($conn , "set names utf8");; h! [# i/ C! R" e! j' ~
  24.     mysqli_select_db( $conn, 'temp' ); 2 i" T8 P) V3 J" N/ q! Z2 B" ~
  25. , ^6 B' W& ?- \7 k; [
  26.     # mysql 锁
    0 w" |" Z; V+ t9 a4 M+ B
  27.     mysqli_query($conn , 'LOCK TABLE a WRITE');// 只有一个客户端可以锁定表,其他客户端阻塞在这
    ' v& P; D, Z6 m) _1 R3 ]
  28.     $rs = mysqli_query($conn , 'SELECT id FROM a');
    7 x) q% |; o& X/ N( s
  29.     $id = mysqli_result($rs, 0, 0); ( x; k, E" k$ E7 s7 q5 N, C
  30.     if($id > 0)
    * b! N' V/ i/ B0 r/ M. F; M
  31.     {
    8 D, t8 T. ?3 K( K4 k1 I  a+ d
  32.         --$id;
    / J  Y' N" K) Y8 C5 L3 p
  33.         mysqli_query($conn , 'UPDATE a SET id='.$id);
    . Z: x1 W% [" z6 _) a: I$ a
  34.     }
    ; Y# H; \8 \! j' W6 e& _

  35. * S% }5 G+ `% _) v: R
  36.     # mysql 解锁
    ' m( E- ~% W% _  P% H
  37.     mysqli_query($conn , 'UNLOCK TABLES');( {. _$ h( \7 x" [. n, r& i
  38.     //查询解锁后的id值
    9 [4 i4 c6 h0 n. v
  39.     // $res = mysqli_query($conn , 'SELECT id FROM ta');. m) }1 x% _$ T) T: j+ @
  40.     // while($row = mysqli_fetch_assoc($res))
    / V( G/ T5 }, C0 ?7 a0 Q& ?, A
  41.     // {  F" y: B( X" G, i3 y2 a  V
  42.     //     $id = $row['id'];
    1 R  m' G9 |9 S1 h5 d% K
  43.     // }
    / x7 n* e$ D4 D2 L3 |+ q+ E
  44.     // echo $id;
复制代码
3 g3 j. ]/ G, ~4 W( G
% O0 V. r" y" g/ P' [- k

0 I3 Y8 N' \) V$ B7 b- `
PHP文件锁示例:
  1. /** s9 b- \. p# e( t/ `
  2.     模拟秒杀活动-- 商品100件
    . e' F7 C( r2 e  s' e8 L' R6 V
  3.     CREATE TABLE ta
    # X  y+ T1 q/ P* Y: ~
  4.     (8 }0 V6 s/ F- p' q  t: \. i$ @& z8 Y
  5.         id int comment '模拟100件活动商品的数量'
    ; a# ^1 d3 f* Z! F) e3 a; A
  6.     );3 S4 a* I5 p) R9 f+ u9 k
  7.     INSERT INTO ta VALUES(100);
    ! C- S0 E/ z4 A, \' Y
  8.     模仿:以10的并发量访问这个脚本!    使用apache自带的ab.exe软件% A- O7 e4 h0 g7 t& s- i" A6 b
  9.      */
    9 @( G  R/ g. S7 o" k
  10.     / k* i, R; {* p/ Q" e
  11.     // 关闭错误报告
    7 r; [+ A( |1 w
  12.      error_reporting(0);
    4 {, ^# [  @0 U" n# x* X5 `" k
  13. . S5 s+ a3 P- Z4 e# D6 ?1 }
  14.      $dbhost = 'localhost:3306';  // mysql服务器主机地址" x' S- Z# n% i/ ~, k
  15.     $dbuser = 'root';            // mysql用户名, s* J# |7 `2 K+ X
  16.     $dbpass = 'root';          // mysql用户名密码
    # E6 s0 r4 U7 m9 c  Q' [
  17.     $conn = mysqli_connect($dbhost, $dbuser, $dbpass);3 r5 J" A. i, P0 s
  18.     if(! $conn ), z+ o, D- S- Z' n0 w% L
  19.     {
    1 E* |2 h- n4 |5 V" o
  20.         die('连接失败: ' . mysqli_error($conn));' m% X$ c# k9 ~- w
  21.     }+ t  B+ x# G( U' Z: j. G
  22.     // 设置编码,防止中文乱码
    ( h) V4 H8 ^8 k. @  |2 }
  23.     mysqli_query($conn , "set names utf8");" z3 I) x  y8 @" a/ C$ i
  24.     mysqli_select_db( $conn, 'temp' ); $ L2 D" F3 u9 b6 O* ?7 T

  25. ! D8 P& i) N0 V3 U2 L; _; N$ F
  26.     # php中的文件锁
    7 b& p  L6 n' I! E3 _
  27.     $fp = fopen('./a.lock', 'r'); // php的文件锁和表没关系,随便一个文件即可 ( E% L7 M5 }/ {2 b) x
  28.     flock($fp, LOCK_EX);// 排他锁
    8 ~, p: v; M6 y1 `( d+ I2 {9 A
  29. ' I0 e  v( [# D2 O% B6 l4 I3 m' ^; _
  30.     $retval = mysqli_query($conn ,'SELECT id FROM ta');
    6 z6 c8 s$ h) d7 B- g, Q
  31.     while($row = mysqli_fetch_assoc($retval))$ u5 n, A' g7 B- D1 V
  32.     {0 P- j' t" _0 }# ?" D2 u) M; u" S
  33.         $id =  $row['id'];
    3 E4 _$ G5 N9 t
  34.     }3 G1 }! i/ K& t' u; t' H
  35.     : H+ v! A; e+ _7 p! Z
  36.     if($id > 0)
    $ i7 A4 d$ V" M* I( u: H
  37.     {
    * X4 M" V& e: f0 a1 J; e1 W1 R6 L4 u
  38.         --$id; ' e% {5 W6 a  v1 A* |! K
  39.         mysqli_query($conn ,'UPDATE ta SET id='.$id);   K4 B5 p' F& T  K1 z
  40.     } / g& W4 Q- H# Z. ?7 j2 r7 O
  41.     # php的文件锁,释放锁
    $ G: B4 Q$ _4 [1 F3 y5 ?0 ]
  42.     flock($fp, LOCK_UN);
    6 o, |% u! b1 x" a# v8 [
  43.     fclose($fp);  B+ d* d- e% S$ k

  44. # {# V0 v# G# Q+ k4 L
  45.     // $res = mysqli_query($conn , 'SELECT id FROM ta');
    8 @1 a: d- }6 R8 u8 ^7 ^4 I
  46.     // while($row = mysqli_fetch_assoc($res))
    1 x8 W/ `, ~& t8 v4 a
  47.     // {
    3 r( c1 Y1 S$ Q/ Q7 Z) U" k7 q/ R
  48.     //     $id = $row['id'];" r5 W! Q4 g7 Z1 w- W
  49.     // }
    5 F$ J. ?; p; B1 T
  50.     // echo $id;
复制代码
. j$ T+ ^- Z' H" j

' J  D' b9 v6 q( H% T7 m: }
抢券活动实例:
  1. public function envelopeSnatching(){
    ) u0 }+ {+ ?5 F. \$ O  x+ N
  2.         $lingqu = $_POST['type'];4 b: @, o5 D% `) ?
  3.         $uid=session('u_id');//用户id
    , a% u" a( }, Y7 K4 F2 `3 Z& d
  4.         if(!$uid){" w( C2 r% J, d' Y" h) }& `
  5.             $data['msg']='您没登录,请先登录!';
    9 x+ u& e5 Z) K" k1 ~' [
  6.         }else if(date('Y-m-d') != '2017-12-12'){% t& m2 M5 x( |3 _* e# ^- C
  7.             $data['msg']='不在活动时间内!';! p( Z1 d4 C7 Z+ L; b
  8.         }else{
    0 D( L& v# f0 T
  9.             $hours=date('H');//当前小时数
    2 c# E2 x$ y  z7 n8 [
  10.             if($hours > '09' || $hours > '17'){, C3 w, j1 ~6 Y7 a! K
  11. 1 u6 h' l7 _9 N; T/ ~) k7 m
  12.                 if($lingqu == 1 || $lingqu ==2){//点击10点的- ^, E, w/ c# |
  13.                     if($lingqu == 1){
    & M" x! a) M* D' d' ~. d0 |
  14.                         $is_lingqu=M('active_log')->field('id')->where(array('num_id'=>1,'uid'=>$uid))->find();//判断是否领取过
    ' U. s. ]& S( T+ r: u3 a) b
  15.                         if($hours > '09'){
    3 k" u  I9 X& }; t6 N8 z
  16.                             $num=mt_rand(25,28);//优惠券金额
    3 H3 f$ Q4 ~4 O' S
  17.                             $id=1;
    ' B  X# d( ~: w( |
  18.                         }# x. P3 H7 r5 e) W( [; h, R7 Q/ A
  19.                     }else if($lingqu == 2){
    2 Y3 [7 w: k6 u6 Z/ s2 |+ L+ ]4 d
  20.                         $is_lingqu=M('active_log')->field('id')->where(array('num_id'=>2,'uid'=>$uid))->find();; L3 e# `2 C/ F! j- Y
  21.                         if($hours > '17'){
    * s! G& ^5 P  H: c9 F- I& j
  22.                             $num=mt_rand(50,55);//优惠券金额9 u$ W( i5 j% S# u+ G9 B" t  a
  23.                             $id=2;- p, ?- P& e1 p" R+ S
  24.                         }: h+ @1 A" G# w. g; [1 Q, Z
  25.                     }
    . V; `1 b6 V4 x$ S
  26.                     if(!$id){+ d8 t9 u8 O7 I; n8 {, E/ o
  27.                         $data['msg']='时间还没到,晚点再来吧。';" d# g- m' W9 Y6 p$ f
  28.                     }else{8 y  X. D$ v' }( y$ h7 ]) W
  29.                         if($is_lingqu){. C( [' L8 f  O7 [$ G2 U
  30.                             $data['msg']='你已经领取过了,留点给别人吧!';8 |9 {" C2 W5 L" ~
  31.                         }else{
    * B" _, g; g9 z  T# g  k: u
  32.                             //锁表, r* d; i7 H  M3 c$ J  `
  33.                             M()->execute('LOCK TABLE active_num WRITE,active_log WRITE');; N2 d3 U( c6 O
  34.                             $active=M('active_num')->where(array('id'=>$id))->find();
      e" \0 ~" b3 c: y  [
  35.                             if($active > 0){8 S* ~; }) j+ ^2 [2 y* g$ e
  36.                                 //开启事务. H  t1 h2 L3 J5 R& a
  37.                                 M()->execute('start transaction');  [3 }$ j! q' ~% c# c  _2 J
  38.                                 $save=M('active_num')->save(array('id'=>$id,'num'=>$active['num']-1));$ Q' M% ]: o" o. R+ m, a6 J) g
  39.                                 $add=M('active_log')->add(array('uid'=>$uid,'money'=>$num,'num_id'=>$id,'addtime'=>time()));+ n, A' I$ Y' J: z* e1 I
  40.                                 $members_preferential    =    M('members_preferential');3 K$ _0 w" R& k& @3 j+ U6 {
  41.                                 //对应投资金额,( R% l% b) ]/ |% b
  42.                                 $key=array_search($num,array_reverse(C('PREFERENTIAL_JL'),true));
    ( w" t  P4 ?2 i7 a* R/ L- ~
  43.                                 $PREFERENTIAL_ENDDAY=C('PREFERENTIAL_ENDDAY');
    7 m) ]: |6 r1 Y# u0 E1 s
  44.                                 $endtime=strtotime("+{$PREFERENTIAL_ENDDAY}day");//过期时间
    & \, m; ?, [  @/ X# m  \
  45.                                 $add2=$members_preferential->add(array('uid'=>$uid,'type'=>$key,'endtime'=>$endtime));//添加优惠券
    ! j' ?) y: |# f; K
  46.                                 if($save && $add && $add2){
      t  a% l- W5 {7 [% F$ `
  47.                                     //事务提交  H. [  h) t: j5 E
  48.                                     M()->execute('commit');9 w  L' }$ B; b/ ]; t9 ?7 X* M
  49.                                     $data['msg']='恭喜你领取了'.$num.'元优惠券';
    8 p! C8 \2 ]+ U  a  r4 O4 z
  50.                                 }else{
    0 o( k. K8 a8 ]# N  d. I. c5 y2 r+ `
  51.                                     //回滚0 m6 H/ Z4 c! ?3 a; d; ?
  52.                                     M()->execute('rollback');9 a; d7 ?! b: m4 C; c1 m( k
  53.                                     $data['msg']='未知错误!';: F$ q: q- S  e
  54.                                 }
    * a( R  }+ F5 a# e; ^
  55.                             }else{- o6 _. q+ i! P5 O* w, U% R: }4 O3 r/ i
  56.                                 $data['msg']='红包已领完,你来晚了!';
    # |0 S, e! l: l  a4 d8 l
  57.                             }
    ! Y  @& b) ^1 j( _* x
  58.                             M()->execute('UNLOCK TABLES');! p9 O3 c& A3 l: O) k, |% ]$ N% O
  59.                         }  S3 ^+ }" @2 O6 B, ?$ z9 r' ^
  60.                     }
    6 D# }: z/ L0 _: s6 e5 q7 U
  61.                 }else{
    " ~% z7 h: W  C. f- x
  62.                     $data['msg']='非法操作!';% l! V9 }& T) A" ^
  63.                 }
    ( }; {* p" [9 s7 e
  64.             }else{
    9 @& D& k. s+ i: o! a( r. p, J
  65.                 $data['msg']='还没有到活动时间,请晚点再来哟!!';( D3 Z! C- K4 S& _# ?* {7 Z1 F
  66.             }: [3 o) U( \; i3 J
  67.         }
    6 E3 k9 O2 e$ n8 S/ n( P
  68.         exit(json_encode($data));, h  g3 x, C- q1 M# [
  69.     }
复制代码

) F: ~( u' K; Y3 n# y: G  d& h/ U/ v& t
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 16:08 , Processed in 0.122106 second(s), 19 queries .

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