浅谈Yii乐观锁的使用及原理


Posted in PHP onJuly 25, 2017

本文介绍了Yii乐观锁的使用及原理,自己做个学习笔记,也分享给大家,希望对大家有用处

原理:

数据表中使用一个int类型的字段来存储版本号,即该行记录的版本号。更新数据时,对比版本号是否一致

sql查询代码如下(伪代码)

update `test_ver` set `name`="lili" and `ver`=2 where `id`=1 and `ver`=1

即在更新时的where查询条件中,带上之前查询记录时得到的版本号,如果其他线程已经修改了该记录,则版本号势必不会一致,则更新失败

示例

数据表

假设有如下数据表

浅谈Yii乐观锁的使用及原理

模型类

appmodelsTestVer

该模型类,重写BaseActiveRecord类中的optimisticLock方法

声明用于记录版本号的字段

/**
 * 乐观锁
 * @return string
 */
public function optimisticLock()
{
 return 'ver';
}

public function updateRecord(){
 $ver = self::findOne(['id'=>1]);
 $ver->name = "lili";
 $res = $ver->update();
 return $res;
}

updateRecord修改id为1的记录

控制器

控制器中调用updateRecord方法

public function actionVersion(){
 $testVer = new TestVer();
 $res = $testVer->updateRecord();
 return $this->render('version');
}

Yii Debugger结果

查看database选项,可以查看到实际执行的sql语句。

有一条语句如下

UPDATE `test_ver` SET `name`='lili', `ver`='2' WHERE (`id`='1') AND (`ver`='1')

Yii乐观锁实现原理

实现原理在yiidbBaseActiveRecord::updateInteranl()方法

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);

 // 获取版本号字段的字段名,比如 ver
 $lock = $this->optimisticLock();

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

  // 这里把旧的版本号作为更新的另一个条件
  $condition[$lock] = $this->$lock;
 }
 $rows = $this->updateAll($values, $condition);

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

从上面的代码中,我们不难得出:

  1. 当 optimisticLock() 返回 null 时,乐观锁不会被启用。
  2. 版本号只增不减。
  3. 通过乐观锁的条件有2个,一是主键要存在,二是要能够完成更新。
  4. 当启用乐观锁后,只有下列两种情况会抛出 StaleObjectException 异常:
    1. 当记录在被别人删除后,由于主键已经不存在,更新失败。
    2. 版本号已经变更,不满足更新的第二个条件。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
用cookies来跟踪识别用户
Oct 09 PHP
对Session和Cookie的区分与解释
Mar 16 PHP
phpinfo 系统查看参数函数代码
Jun 05 PHP
PHP 函数语法介绍一
Jun 14 PHP
php中getservbyport与getservbyname函数用法实例
Nov 18 PHP
php中adodbzip类实例
Dec 08 PHP
php技术实现加载字体并保存成图片
Jul 27 PHP
php 在字符串指定位置插入新字符的简单实现
Jun 28 PHP
PHP实现字符串翻转功能的方法【递归与循环算法】
Nov 03 PHP
PHP性能分析工具xhprof的安装使用与注意事项
Dec 19 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
Apr 05 PHP
Thinkphp5框架中引入Markdown编辑器操作示例
Jun 03 PHP
PHP异常处理定义与使用方法分析
Jul 25 #PHP
PHP实现防盗链的方法分析
Jul 25 #PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 #PHP
php 删除指定文件夹的实例讲解
Jul 25 #PHP
Laravel5.* 打印出执行的sql语句的方法
Jul 24 #PHP
PHP实现时间比较和时间差计算的方法示例
Jul 24 #PHP
PHP实现的登录页面信息提示功能示例
Jul 24 #PHP
You might like
php中jQuery插件autocomplate的简单使用笔记
2012/06/14 PHP
yii2.0实现验证用户名与邮箱功能
2015/12/22 PHP
php设计模式之委托模式
2016/02/13 PHP
thinkPHP交易详情查询功能详解
2016/12/02 PHP
利用PHP访问带有密码的Redis方法示例
2017/02/09 PHP
php 读写json文件及修改json的方法
2018/03/07 PHP
Laravel框架在本地虚拟机快速安装的方法详解
2018/06/11 PHP
学习ExtJS TextField常用方法
2009/10/07 Javascript
JavaScript 数组运用实现代码
2010/04/13 Javascript
关于js数组去重的问题小结
2014/01/24 Javascript
详谈jQuery中的this和$(this)
2014/11/13 Javascript
javascript限制用户只能输汉字中文的方法
2014/11/20 Javascript
14个有用的Jquery技巧分享
2015/01/08 Javascript
AngularJS验证信息框架的封装插件用法【w5cValidator扩展插件】
2016/11/03 Javascript
Vue 进阶教程之v-model详解
2017/05/06 Javascript
微信小程序getPhoneNumber获取用户手机号
2017/09/29 Javascript
JavaScript常见事件处理程序实例总结
2019/01/05 Javascript
详解VUE项目中安装和使用vant组件
2019/04/28 Javascript
vue父子组件通信的高级用法示例
2019/08/29 Javascript
详解vue之自行实现派发与广播(dispatch与broadcast)
2021/01/19 Vue.js
Python实现树的先序、中序、后序排序算法示例
2017/06/23 Python
python使用udp实现聊天器功能
2018/12/10 Python
浅谈Pytorch torch.optim优化器个性化的使用
2020/02/20 Python
美国内衣品牌:Leonisa
2016/08/14 全球购物
美国宠物商店:Wag.com
2016/10/25 全球购物
New Balance天猫官方旗舰店:始于1906年,百年慢跑品牌
2017/11/15 全球购物
英国领先的杂志订阅网站:Magazine.co.uk
2018/01/25 全球购物
写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分隔
2015/07/30 面试题
商务英语毕业生自荐信范文
2013/11/08 职场文书
公司新年寄语
2014/04/04 职场文书
通信工程求职信
2014/07/16 职场文书
2014年小学校长工作总结
2014/12/08 职场文书
先进班集体事迹材料
2014/12/25 职场文书
伊索寓言读书笔记
2015/06/30 职场文书
建议书的格式及范文
2015/09/14 职场文书
2015年乡镇组织委员工作总结
2015/10/23 职场文书