mysql锁、PHP锁防止高并发出错的机制

编辑:睿儿发表于:2021-05-23 21:43:45 112 次阅读

mysql锁


error_reporting(0);
mysql_connect('localhost','root','XXXXX');
mysql_select_db('DBNAME');
 
# mysql 锁
mysql_query('LOCK TABLE DBNAME WRITE');// 只有一个客户端可以锁定表,其他客户端阻塞在这
$rs = mysql_query('SELECT id FROM DBNAME');
$id = mysql_result($rs, 0, 0);
if($id > 0)
{
    --$id;
    mysql_query('UPDATE DANAME SET id='.$id);
}
 
# mysql 解锁
mysql_query('UNLOCK TABLES');



php锁


$fp = fopen('./a.lock', 'r'); // php的文件锁和表没关系,随便一个文件即可
flock($fp, LOCK_EX);// 排他锁
.....
你的操作过程
....
# php的文件锁,释放锁
flock($fp, LOCK_UN);
fclose($fp);



为什么我们要使用锁来把记录锁起来?

在一些并发量很高的业务中,比如 秒杀、下单【有一定库存的】,如果我们不把业务流程锁定了,很容易出现错误,比如秒杀很多人同时成功、卖东西超出库存等。所以在特定的环境下,我们需要把业务 逻辑加上锁,然后再跑,以此来保证数据的准确性。



MYSQL记录锁

$pdo = new PDO('mysql:host=127.0.0.1;port=3306; dbname=test','root','123456');
$pdo->beginTransaction();//开启事务
$sql="select `number` from storage where id=1 for UPDATE ";//利用for update 开启行锁
$res = $pdo->query($sql)->fetch();
$number = $res['number'];
 
if($number>0)
{
  $sql ="insert into `order` VALUES (null,$number)";
 
  $order_id = $pdo->query($sql);
  if($order_id)
  {
 
    $sql="update storage set `number`=`number`-1 WHERE id=1";
    if($pdo->query($sql))
    {
      $pdo->commit();//提交事务
    }
    else
    {
      $pdo->rollBack();//回滚
    }
 
  }
  else
  {
    $pdo->rollBack();//回滚
  }
}


以下是在网上查的一些相关资料总结的方法。

----------------------------------------------------------------------------------------------------------------------------------------


什么是悲观锁?就是比较,不相信其它的人不会改,所以查询的时候就加锁,然后自己更新数据再释放锁。可以有效防止减库存冲突问题。

什么是乐观锁?就是认为没几个人用,基本不会碰到有人修改,所以查询时就不加锁,然后更新的时候判断一下数据是不是被改掉。

悲观锁的业务流程:

---事务开始

查询商品表、锁定表:for update

判断商品库存是否大于购买数据,

如果库存满足,减少商品表库存。(不满足就回滚事务了。)

否则就回滚事务

--事务提交(事务提交时即释放锁)。

上面的流程中整个被锁的周期是比较长的。


乐观锁业务流程:

----事务开始

1,查询商品表(把库存数量保存到变量)

2,判断商品库存是否大于购买数据,

3,如果库存满足,减少商品表库存(条件是商品表的库存=1中查询出的库存)

比如:update 产品表 set 库存 = 库存 - 数量 where 库存 = 之前保存的库量数量的变量

如果不等则不更新,回滚事务。

--事务提交

可以看到乐观锁整个过程中实际并未执行任何加锁。实际它是一种判断冲突的有效手段。

在上面的乐观锁的执行流程中,如果3发生异常,会回滚事务。这样就不会出现减库存冲突导致库存出错。

在使用乐观锁时,要考虑进一步,就是在乐观锁时如果发现数据被修改,更新失败时,要考虑再重新获取数据,重新判断重新更新。这样就不会因为更新失败导致此笔业务失败,而相当于把它立即加进到下一步的队列而在同步请求中即能得到解决,但如果特别高并发的时候,库存数会一直变,及有可能每次都不一样,这样的话可能会限入更新库存的死循环。

必须面对高并发的情况下,如果使用乐观锁,需要认真测试一下会不会让业务一直处于死循环状态。

-----------------------------------------------------------------------------------------------------------------------------------------------------


但是在我实际应用的投票项目中,每天几万的数据,没有记录锁,也没有出过问题,可能几万数据只能算并发,根本算不上高并发的范围。

原文地址:http://www.zjkdh.com/library/202105/88.html(张家口导航-睿儿知识库)

张家口睿儿网络科技有限公司版权所有