共计 3189 个字符,预计需要花费 8 分钟才能阅读完成。
一:在 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();
}