一:在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 字段,能够为乐观锁所用

2:实现乐观锁

咱们在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();}