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

MySQL乐观锁是建立在悲观锁的基础上的

时间:2023-03-29 22:22:15 PHP

MySQL5.5以后默认使用innoDb数据引擎。本文使用默认存储引擎。乐观锁乐观锁其实是一种逻辑思想,并不是mysql数据库的特性。这个应该区分清楚。实现数据版本控制有两种方式,第一种是使用版本号,第二种是使用时间戳。使用方法:/**伪码编号库存goods_id商品IDversion版本号默认为0**/$sql="selectnumberfromgoodswheregoods_id={$goods_id}andversion={$version}";//time戳查询库存$sql="selectnumberfromgoodswheregoods_id={$goods_id}andtimefetch_assoc();if($row['number']>0){//高并发会导致超卖if($row['number']<$number){returninsertLog('库存不足',3,$username);}//减库存$sql="updategoodssetnumber=number-{$number},version+=1wheregoods_id={$goods_id}andnumber>0";//减库存的时间戳方式$sql="更新商品集number=number-{$number},time=time()wheregoods_id={$goods_id}andnumber>0";$store_rs=mysqli_query($conn,$sql);if($store_rs){//生成订单,返回操作成功echojson_encode(array('code'=>0,'msg'=>'减库存成功','data'=>$username));}else{echojson_encode(array('code'=>1,'msg'=>'减库存失败','data'=>$username));}}else{echojson_encode(array('code'=>3,'msg'=>'减库存失败','达ta'=>$username));}注意:使用乐观锁需要注意。将库存字段编号字段设置为无符号。当库存为0时,因为该字段不能为负,所以会返回false悲观锁。是对数据被外界修改(包括系统当前的其他事务,以及来自外部系统的事务处理)的一种保守态度。因此,在整个数据处理过程中,让数据一直处于锁定状态的悲观锁的实现往往依赖于数据库提供的锁定机制(只有数据库层提供的锁定机制才能真正保证数据访问的排他性,否则,即使本系统实现了锁定机制,也不能保证外部系统不会修改数据)。悲观锁定利用了MySQLinnoDB存储引擎的行锁定功能。逐行操作数据。使用方法://使用悲观锁锁定当前行$sql="selectnumberfromgoodswheregoods_id={$goods_id}forupdate";//减少库存操作$sql="updategoodssetnumber=number-{$number}wheregoods_id={$goods_id}andnumber>0";注意:innoDB行锁是基于索引执行的,where条件后面必须有索引,否则会进行全表扫描。优缺点:悲观并发控制实际上是一种“先拿锁再访问”的保守策略,为数据处理的安全性提供了保障。但是从效率上来说,锁机制会给数据库带来额外的开销,增加死锁的几率;另外,由于只读事务处理不会有冲突,所以也不需要使用锁。只能增加系统负载;它还将减少并行性。如果一个事务锁定了一行数据,其他事务必须等待该事务处理完毕才能处理该行数。乐观并发控制认为事务(datarace)之间的数据竞争比较小,所以尽量直接做,提交之前不要加锁,所以不会出现加锁和死锁的情况。但是,如果你直接简单地这样做,你仍然可能会遇到意想不到的结果。比如两个事务都读取数据库的某一行,修改后写回数据库。这时候,你就遇到了问题。建议:在并发量不大的应用场景下,使用乐观锁。在数据一致性要求高的情况下,可以牺牲性能,使用悲观锁。这两种方式的前提是采用MySQL方案。