首页后端开发PHPYii中乐观锁和悲观锁的用法和用途有哪些,如何实现

Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现

时间2024-03-22 07:25:03发布访客分类PHP浏览740
导读:这篇文章主要给大家介绍“Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现...
这篇文章主要给大家介绍“Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现”文章能对大家有所帮助。

    

目录
  • 一、在Yii中实现乐观锁
    • 1、在yii中实现乐观锁步骤
    • 2、Yii中实现乐观锁
    • 3、实现乐观锁
  • 二、在Yii中实现悲观锁
    • 1、在yii中实现悲观锁的步骤
    • 2、yii中悲观锁实现

一、在Yii中实现乐观锁

乐观锁(optimistic locking)表现出大胆、务实的态度。使用乐观锁的前提是, 实际应用当中,发生冲突的概率比较低。他的设计和实现直接而简洁。 目前Web应用中,乐观锁的使用占有绝对优势。因此在Yii为ActiveReocrd乐观锁支持

1、在yii中实现乐观锁步骤

1、给需要加锁的表添加一个字段,用于表示版本号,这里我一般选手version字段作为版本号字段,注意,如果你需要加锁的表已经生成Model了,那么对应表的Model要将你添加的版本号字段(version)信息加入Model

2、在更新表中字段时,使用 try ... catch 看看是否能捕获一个 yii\db\StaleObjectException 异常,如果捕捉到yii\db\StaleObjectException 异常,说明在本次修改这个记录的过程中, 该记录已经被修改过了,作出相应提示

2、Yii中实现乐观锁

1、在yii中声明指定字段为版本号

版本号是实现乐观锁的根本所在。所以第一步,我们要告诉Yii,哪个字段是版本号字段,声明版本号的方法由yii\db\BaseActiveRecord(vendor/yiisoft/yii2/db/BaseActiveRecord)中的optimisticLock方法负责

public function optimisticLock()
{
    
    return null;

}

这个方法返回 null ,表示不使用乐观锁,如果我们需要使用乐观锁的话,我们需要在我们的需要加锁的表的Model中重载optimisticLock方法

public function optimisticLock()
{
    
    return 'version';

}

如上说明当前的ActiveRecord中,有一个 version 字段,可以为乐观锁所用

3、实现乐观锁

我们在Model中设置了版本号后,这时候我们的更新和删除都是乐观锁操作了,与正常操作数据库的方式一致

try {
    
    $crowd = Crowd::findOne(['crowd_id' =>
     12]);
    
    $crowd->
    status = 1;
    
    $crowd->
    save();

}
 catch (\Exception $e) {
    
    return false;

}

在更新过程中,我们会调用到 yii\db\BaseActiveRecord::updateInternal()方法,此方法里面就具有处理乐观锁的代码

protected function updateInternal($attributes = null)
{
    
    if (!$this->
beforeSave(false)) {
    
      return false;

    }
    
    // 获取等下要更新的字段及新的字段值
    $values = $this->
    getDirtyAttributes($attributes);

    if (empty($values)) {
    
      $this->
    afterSave(false, $values);
    
      return 0;

    }
    
    // 把原来ActiveRecord的主键作为等下更新记录的条件,也就是说,等下更新的,最多只有1个记录。
    $condition = $this->
    getOldPrimaryKey(true);
    
    // 获取版本号字段的字段名,比如 version
    $lock = $this->
    optimisticLock();

    // 如果 optimisticLock() 返回的是 null,那么,不启用乐观锁。
    if ($lock !== null) {
    
    // 这里的 $this->
    $lock ,就是 $this->
    version 的意思; 这里把 version+1 作为要更新的字段之一。
      $values[$lock] = $this->
    $lock + 1;
    
      // 这里把旧的版本号作为更新的另一个条件
      $condition[$lock] = $this->
    $lock;

    }
    
    $rows = static::updateAll($values, $condition);
    
// 如果已经启用了乐观锁,但是却没有完成更新,或者更新的记录数为0;
  // 那就说明是由于 version 不匹配,记录被修改过了,于是抛出异常。
    if ($lock !== null &
    &
 !$rows) {
    
      throw new StaleObjectException('The object being updated is outdated.');

    }

    if (isset($values[$lock])) {
    
      $this->
    $lock = $values[$lock];

    }
    
    $changedAttributes = [];
    
    foreach ($values as $name =>
 $value) {
    
      $changedAttributes[$name] = isset($this->
    _oldAttributes[$name]) ? $this->
    _oldAttributes[$name] : null;
    
      $this->
    _oldAttributes[$name] = $value;

    }
    
    $this->
    afterSave(false, $changedAttributes);
    
    return $rows;

}

在删除过程中,我们会调用到 yii\db\BaseActiveRecord::delete()方法,此方法里面就具有处理乐观锁的代码

public function delete()
    {
    
        $result = false;
    
        if ($this->
beforeDelete()) {
    
            // 删除的SQL语句中,WHERE部分是主键
            $condition = $this->
    getOldPrimaryKey(true);
    
            // 获取版本号字段的字段名,比如 version
            $lock = $this->
    optimisticLock();

            // 如果启用乐观锁,那么WHERE部分再加一个条件,版本号
            if ($lock !== null) {
    
                $condition[$lock] = $this->
    $lock;

            }
    
            $result = static::deleteAll($condition);
    
            if ($lock !== null &
    &
 !$result) {
    
                throw new StaleObjectException('The object being deleted is outdated.');

            }
    
            $this->
    _oldAttributes = null;
    
            $this->
    afterDelete();

        }
    
        return $result;

    }
    

如上我们就知道了,在yii中已经有了乐观锁相关的代码了,我们只需要在Model中设置一个版本号字段即可

二、在Yii中实现悲观锁

正如其名字,悲观锁(pessimistic locking)体现了一种谨慎的处事态度

1、在yii中实现悲观锁的步骤

1、在对任意记录进行修改前,先尝试为该记录加上锁

2、如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常

3、如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了

2、yii中悲观锁实现

使用select.....for update实现悲观锁,简单示例如下:

$transaction = Yii::$app->
    db->
    beginTransaction();

try{
    
    //查询id为12的这条数据并且锁定
    $sql = "select * from ubo_crowd where crowd_id = 12 for update";
    
    $crowd = Yii::$app->
    db->
    createCommand($sql)->
    queryOne();
    
    //更新数据
    $crowd1 = Crowd::findOne(['crowd_id' =>
     $crowd['crowd_id']]);
    
    $crowd1->
    sort += 1;
    
    if($crowd1->
save()){
    
        $transaction->
    commit();

    }

}
catch(Exception $e){
    
    $transaction->
    rollBack();

}
    



通过以上内容的阐述,相信大家对“Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现”已经有了进一步的了解,更多相关的问题,欢迎关注网络或到官网咨询客服。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Yii中乐观锁和悲观锁的用法和用途有哪些,如何实现
本文地址: https://pptw.com/jishu/650198.html
生成器会对PHP应用的性能真的影响很大吗 mybatis用oracle添加数据怎么操作,有什么要注意的

游客 回复需填写必要信息