浅谈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 相关文章推荐
php zend 相对路径问题
Jan 12 PHP
php中对2个数组相加的函数
Jun 24 PHP
解析如何用php screw加密php源代码
Jun 20 PHP
curl和libcurl的区别简介
Jul 01 PHP
win7系统配置php+Apache+mysql环境的方法
Aug 21 PHP
yii gridview实现时间段筛选功能
Aug 15 PHP
php 替换文章中的图片路径,下载图片到本地服务器的方法
Feb 06 PHP
PHP生成腾讯云COS接口需要的请求签名
May 20 PHP
PHP asXML()函数讲解
Feb 03 PHP
PHP7匿名类的用法示例
Apr 05 PHP
PHP文件类型检查及fileinfo模块安装使用详解
May 09 PHP
ThinkPHP 5 AJAX跨域请求头设置实现过程解析
Oct 28 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重定向的三种方法分享
2012/02/22 PHP
php类常量用法实例分析
2015/07/09 PHP
ThinkPHP表单令牌错误的相关解决方法分析
2016/05/20 PHP
Yii2框架dropDownList下拉菜单用法实例分析
2016/07/18 PHP
详解Yii实现分页的两种方法
2017/01/14 PHP
PHP实现Session入库/存入redis的方法
2017/05/04 PHP
PHP命名空间(namespace)原理与用法详解
2019/12/11 PHP
总结JavaScript设计模式编程中的享元模式使用
2016/05/21 Javascript
深入研究jQuery图片懒加载 lazyload.js使用方法
2017/08/16 jQuery
如何理解Vue的render函数的具体用法
2017/08/30 Javascript
VUE DEMO之模拟登录个人中心页面之间数据传值实例
2019/10/31 Javascript
详解关于Vue单元测试的几个坑
2020/04/26 Javascript
解决vue项目运行npm run serve报错的问题
2020/10/26 Javascript
JavaScript函数柯里化实现原理及过程
2020/12/02 Javascript
[03:28]2014DOTA2国际邀请赛 EG战队官方纪录片
2014/07/21 DOTA
python调用机器喇叭发出蜂鸣声(Beep)的方法
2015/03/23 Python
Python实现的数据结构与算法之链表详解
2015/04/22 Python
python 调用c语言函数的方法
2017/09/29 Python
python使用pygame框架实现推箱子游戏
2018/11/20 Python
Python设计模式之桥接模式原理与用法实例分析
2019/01/10 Python
Python 迭代,for...in遍历,迭代原理与应用示例
2019/10/12 Python
python基于socket实现的UDP及TCP通讯功能示例
2019/11/01 Python
Tensorflow轻松实现XOR运算的方式
2020/02/03 Python
Tensorflow--取tensorf指定列的操作方式
2020/06/30 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
Lee牛仔裤澳大利亚官网:美国著名牛仔裤品牌
2017/09/02 全球购物
专业毕业生个性的自我评价
2013/10/03 职场文书
医学生自荐信
2013/12/03 职场文书
优秀家长事迹材料
2014/05/17 职场文书
孝敬父母的活动方案
2014/08/31 职场文书
国庆节标语大全
2014/10/08 职场文书
2014年英语教研组工作总结
2014/12/06 职场文书
采购内勤岗位职责
2015/04/13 职场文书
2016高考感言
2015/08/01 职场文书
SpringAop日志找不到方法的处理
2021/06/21 Java/Android
教你使用Jenkins集成Harbor自动发布镜像
2022/04/03 Servers