浅谈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 相关文章推荐
基于文本的访客签到簿
Oct 09 PHP
模仿OSO的论坛(三)
Oct 09 PHP
PHP 翻页 实例代码
Aug 07 PHP
9个PHP开发常用功能函数小结
Jul 15 PHP
PHP可变函数的使用详解
Jun 14 PHP
浅析php变量作用域的一些问题
Aug 08 PHP
php建立Ftp连接的方法
Mar 07 PHP
PHP学习笔记(二):变量详解
Apr 17 PHP
php读取der格式证书乱码解决方法
Jun 22 PHP
thinkphp实现分页显示功能
Dec 03 PHP
php查找字符串中第一个非0的位置截取
Feb 27 PHP
php常用日期时间函数实例小结
Jul 04 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
Oracle 常见问题解答
2006/10/09 PHP
MVC模式的PHP实现
2006/10/09 PHP
请php正则走开
2008/03/15 PHP
PHP编码转换
2012/11/05 PHP
php curl登陆qq后获取用户信息时证书错误
2015/02/03 PHP
php5.4传引用时报错问题分析
2016/01/22 PHP
PHP socket 模拟POST 请求实例代码
2016/07/18 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
JS中处理与当前时间间隔的函数代码
2012/05/23 Javascript
使用js 设置url参数
2013/07/08 Javascript
Angularjs使用directive自定义指令实现attribute继承的方法详解
2016/08/05 Javascript
react.js 获取真实的DOM节点实例(必看)
2017/04/17 Javascript
JavaScrpt判断一个数是否是质数的实例代码
2017/06/11 Javascript
JavaScript截屏功能的实现代码
2017/07/28 Javascript
微信小程序实现点击按钮修改文字大小功能【附demo源码下载】
2017/12/06 Javascript
node实现登录图片验证码的示例代码
2018/04/20 Javascript
JS立即执行函数功能与用法分析
2019/01/15 Javascript
vue随机验证码组件的封装实现
2020/02/19 Javascript
vuex(vue状态管理)的特殊应用案例分享
2020/03/03 Javascript
如何在selenium中使用js实现定位
2020/08/18 Javascript
Python的时间模块datetime详解
2017/04/17 Python
使用pandas将numpy中的数组数据保存到csv文件的方法
2018/06/14 Python
解决pycharm 远程调试 上传 helpers 卡住的问题
2019/06/27 Python
Django为窗体加上防机器人的验证码功能过程解析
2019/08/14 Python
用python监控服务器的cpu,磁盘空间,内存,超过邮件报警
2021/01/29 Python
努比亚手机官网:nubia
2016/10/06 全球购物
100%有机精油,美容油:House of Pure Essence
2018/10/30 全球购物
监理员的岗位职责
2013/11/13 职场文书
事业单位接收函
2014/01/10 职场文书
安全生产检讨书
2014/01/21 职场文书
校运会入场式解说词
2014/02/10 职场文书
兵马俑的导游词
2015/02/02 职场文书
工程部部长岗位职责
2015/02/12 职场文书
党支部工作总结2015
2015/04/01 职场文书
六一文艺汇演主持词
2015/06/30 职场文书
2015年暑期社会实践总结
2015/07/13 职场文书