深入理解Yii2.0乐观锁与悲观锁的原理与使用
副标题[/!--empirenews.page--]
本文介绍了深入理解Yii2.0乐观锁与悲观锁的原理与使用,分享给大家,具体如下: Web应用往往面临多用户环境,这种情况下的并发写入控制, 几乎成为每个开发人员都必须掌握的一项技能。 在并发环境下,有可能会出现脏读(Dirty Read)、不可重复读(Unrepeatable Read)、 幻读(Phantom Read)、更新丢失(Lost update)等情况。具体的表现可以自行搜索。 为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念。 这里我们都不作解释了,拿这些关键词一搜,网上大把大把的。 但是,就于具体开发过程而言,一般分为悲观锁和乐观锁两种方式来解决并发冲突问题。 乐观锁乐观锁(optimistic locking)表现出大胆、务实的态度。使用乐观锁的前提是, 实际应用当中,发生冲突的概率比较低。他的设计和实现直接而简洁。 目前Web应用中,乐观锁的使用占有绝对优势。 因此,Yii也为ActiveReocrd提供了乐观锁支持。 根据Yii的官方文档,使用乐观锁,总共分4步:
从本质上来讲,乐观锁并没有像悲观锁那样使用数据库的锁机制。 乐观锁通过在表中增加一个计数字段,来表示当前记录被修改的次数(版本号)。 然后在更新、删除前通过比对版本号来实现乐观锁。 声明版本号字段版本号是实现乐观锁的根本所在。所以第一步,我们要告诉Yii,哪个字段是版本号字段。 这个由 yiidbBaseActiveRecord 负责: 这个方法返回 null ,表示不使用乐观锁。那么我们的Model中,要对此进行重载。 返回一个字符串,表示我们用于标识版本号的字段。比如可以这样: 说明当前的ActiveRecord中,有一个 ver 字段,可以为乐观锁所用。 那么Yii具体是如何借助这个 ver 字段实现乐观锁的呢? 更新过程具体来讲,使用乐观锁之后的更新过程,就是这么一个流程:
由于ActiveRecord的更新过程最终都需要调用 // 获取版本号字段的字段名,比如 ver // 如果 optimisticLock() 返回的是 null,那么,不启用乐观锁。
} // 如果已经启用了乐观锁,但是却没有完成更新,或者更新的记录数为0; 从上面的代码中,我们不难得出:
删除过程与更新过程相比,删除过程的乐观锁,更简单,更好理解。代码仍在 yiidbBaseActiveRecord 中: beforeDelete()) { // 删除的SQL语句中,WHERE部分是主键 $condition = $this->getOldPrimaryKey(true); // 获取版本号字段的字段名,比如 ver $lock = $this->optimisticLock(); // 如果启用乐观锁,那么WHERE部分再加一个条件,版本号 if ($lock !== null) { $condition[$lock] = $this->$lock; } $result = $this->deleteAll($condition); if ($lock !== null && !$result) { throw new StaleObjectException('The object being deleted is outdated.'); } $this->_oldAttributes = null; $this->afterDelete(); } return $result; }比起更新过程,删除过程确实要简单得多。唯一的区别就是省去了版本号+1的步骤。 都要删除了,版本号+1有什么意义? 乐观锁失效(编辑:瑞安网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |