浅谈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 采集程序中常用的函数
Dec 09 PHP
php empty,isset,is_null判断比较(差异与异同)
Oct 19 PHP
php4与php5的区别小结(配置异同)
Dec 20 PHP
php实现memcache缓存示例讲解
Dec 04 PHP
php获取访问者IP地址汇总
Apr 24 PHP
PHP中配置IIS7实现基本身份验证的方法
Sep 24 PHP
PHP socket 模拟POST 请求实例代码
Jul 18 PHP
PHP 500报错的快速解决方法
Dec 14 PHP
PHP让数组中有相同值的组成新的数组实例
Dec 31 PHP
Yii框架函数简单用法分析
Sep 09 PHP
php获取是星期几的的一些常用姿势
Dec 15 PHP
laravel ajax curd 搜索登录判断功能的实现
Apr 17 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
国产动画《伍六七》原声大碟大卖,啊哈娱乐引领音乐赋能IP的新尝试
2020/03/08 国漫
php获取textarea的值并处理回车换行的方法
2014/10/20 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
PHP数组相加操作及与array_merge的区别浅析
2016/11/26 PHP
phpinfo无法显示的原因及解决办法
2019/02/15 PHP
Jquery index()方法 获取相应元素索引值
2012/10/12 Javascript
模拟jQuery中的ready方法及实现按需加载css,js实例代码
2013/09/27 Javascript
js中hash和ico的关联分析
2015/02/05 Javascript
jQuery解析json格式数据简单实例
2016/01/22 Javascript
修改jquery中dialog的title属性方法(推荐)
2016/08/26 Javascript
js控制div层的叠加简单方法
2016/10/15 Javascript
详解.vue文件中style标签的几个标识符
2018/07/17 Javascript
Node.js+ELK日志规范的实现
2019/05/23 Javascript
聊聊Vue 中 title 的动态修改问题
2019/06/11 Javascript
JavaScript对象属性操作实例解析
2020/02/04 Javascript
Javascript confirm多种使用方法解析
2020/09/25 Javascript
[41:08]2014 DOTA2国际邀请赛中国区预选赛 HGT VS NE
2014/05/22 DOTA
实例解析Python的Twisted框架中Deferred对象的用法
2016/05/25 Python
django文档学习之applications使用详解
2018/01/29 Python
Python+PIL实现支付宝AR红包
2018/02/09 Python
pyqt5 使用cv2 显示图片,摄像头的实例
2019/06/27 Python
使用python批量修改文件名的方法(视频合并时)
2020/03/24 Python
django项目中新增app的2种实现方法
2020/04/01 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
2020/09/02 Python
西班牙拥有最佳品牌的动物商店:Animalear.com
2018/01/05 全球购物
viagogo意大利票务平台:演唱会、体育比赛、戏剧门票
2018/01/26 全球购物
构造方法和其他方法的区别
2016/04/26 面试题
高中生毕业学习总结的自我评价
2013/11/14 职场文书
大专生简历的自我评价
2013/11/26 职场文书
批评与自我批评材料
2014/02/15 职场文书
计算机软件专业求职信
2014/06/10 职场文书
承诺书模板
2014/08/30 职场文书
党的群众路线教育实践活动对照检查材料(教师)
2014/09/24 职场文书
浅谈Python中的函数(def)及参数传递操作
2021/05/25 Python
nginx 配置指令之location使用详解
2022/05/25 Servers
Django框架中模型的用法
2022/06/10 Python