当前位置: 首页 > 后端技术 > PHP

Mysql的锁机制和PHP文件锁处理高并发和简单的思路

时间:2023-03-29 15:33:35 PHP

以购买商品为例:①从数据库中获取库存数量。②检查库存数量是否充足。③库存数量减去买家购买的数量(以每个用户一个为例)。④最后完成购买。只有这几行逻辑代码在并发的情况下会出问题,大家自己想象吧。这里暂时不做测试,下面给出并发处理的测试结果。创建表:CREATETABLE`warehouse`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'id',`stock`int(11)NOTNULLDEFAULT'0'COMMENT'stock',PRIMARYKEY(`id`))ENGINE=MyISAMAUTO_INCREMENT=3DEFAULTCHARSET=utf8第一个选项使用Mysql锁(与表引擎无关)。共享锁:每个人都可以读取一个资源,但只有获得锁的人才能操作;独占锁:只有获得资源的对象才能操作资源,其他人不能操作,也不能读。句法:LOCKTABLEaREAD,bWRITE,cREAD,dWRITE;(可以锁定多个表,在表锁定过程中只能操作被锁定的表,不能操作其他表)。解锁表;(释放表)。@$mysql=mysql_connect('localhost','root','');mysql_query('setnamesutf8');mysql_select_db('test');mysql_query('LOCKTABLE`warehouse`WRITE');//锁表之后只能一个人同时操作,即只有一个人能拿到锁$sql='SELECT`stock`FROMwarehouse';$res=mysql_query($sql);$row=mysql_fetch_array($res);$stock=$row[0];if($stock<1){die('库存不足');}else{$new_stock=intval($stock-1);mysql_query('UPDATE仓库SET`stock`='.$new_stock);mysql_query('UPDATETABLES');}加锁表的缺点是:会有阻塞,如果同时加锁多个表,也会影响整个网站相关表的加载。第二种选择是使用PHP的文件锁。特点:调用flock加锁文件时,如果没有获取到锁,会直接返回FALSE,不会阻塞。独占锁:flock($fp,LOCK_EX);共享锁:flock($fp,LOCK_SH);释放锁:flock($fp,LOCK_UN);@$mysql=mysql_connect('localhost','root','');mysql_query('setnamesutf8');mysql_select_db('test');$fp=fopen('./lock.txt','r');$try=10;//声明一个变量来表示获取的次数,防止死循环do{$lock=flock($fp,LOCK_EX);如果(!$锁)usleep(5000);//如果没有获取到锁,释放CPU,休息5000毫秒}while(!$lock&&--$try>=0);if($lock){$sql='SELECT`stock`FROMwarehouse';$res=mysql_query($sql);$row=mysql_fetch_array($res);$stock=$row[0];if($stock<1){die('库存不足');}else{$new_stock=intval($stock-1);mysql_query('UPDATE仓库SET`stock`='.$new_stock);}flock($fp,LOCK_UN);fclose($fp);}else{die('系统正忙!');}第三种方案,一条简单的SQL语句就可以防止仓库被负数。@$mysql=mysql_connect('localhost','root','');mysql_query('setnamesutf8');mysql_select_db('test');mysql_query('UPDATEwarehouseSET`stock`=`stock`-1WHERE`库存`>0');//避免负库存测试的方法是在Apache下找到ab.exe,将其拖入CMD终端,然后输入指定参数test。具体参数谷歌解释一下就知道了,比如耗时之类的……这里就不细说了。PS:Mysql的表锁和PHP的文件锁在处理并发数上也是不一样的,大家可以多测试。无论如何,有很多选择

最新推荐
猜你喜欢