浅谈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 19 PHP
PHP中替换换行符的几种方法小结
Oct 15 PHP
Ubuntu12下编译安装PHP5.3开发环境
Mar 27 PHP
Symfony2实现从数据库获取数据的方法小结
Mar 18 PHP
ThinkPHP项目分组配置方法分析
Mar 23 PHP
PHP MVC框架skymvc支持多文件上传
May 26 PHP
php判断是否为ajax请求的方法
Nov 29 PHP
PHP后端银联支付及退款实例代码
Jun 23 PHP
一个非常实用的php文件上传类
Jul 04 PHP
PHP对称加密算法(DES/AES)类的实现代码
Nov 14 PHP
使用PHP反射机制来构造"CREATE TABLE"的sql语句
Mar 21 PHP
phpcmsv9.0任意文件上传漏洞解析
Oct 20 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
DC动画电影《黑暗正义联盟》曝预告 5月5日上线数字平台
2020/04/09 欧美动漫
php代码把全角数字转为半角数字
2007/12/10 PHP
php数组查找函数in_array()、array_search()、array_key_exists()使用实例
2014/04/29 PHP
PHP常用正则表达式集锦
2014/08/17 PHP
Dojo之路:如何利用Dojo实现Drag and Drop效果
2007/04/10 Javascript
jquery 插件 任意位置浮动固定层
2008/12/25 Javascript
Javascript限制网页只能在微信内置浏览器中访问
2014/11/09 Javascript
Servlet实现文件上传,可多文件上传示例
2016/12/05 Javascript
详解webpack多页面配置记录
2018/01/22 Javascript
React styled-components设置组件属性的方法
2018/08/07 Javascript
TypeScript的安装、使用、自动编译的实现
2020/04/10 Javascript
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
关于angular 8.1使用过程中的一些记录
2020/11/25 Javascript
[00:17]游戏风云独家报道:DD赛后说出数字秘密 吓死你们啊!
2014/07/13 DOTA
python中定义结构体的方法
2013/03/04 Python
python使用线程封装的一个简单定时器类实例
2015/05/16 Python
Python Selenium参数配置方法解析
2020/01/19 Python
详解使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)
2020/04/01 Python
关于matplotlib-legend 位置属性 loc 使用说明
2020/05/16 Python
Python如何向SQLServer存储二进制图片
2020/06/08 Python
Python collections.defaultdict模块用法详解
2020/06/18 Python
python绘制趋势图的示例
2020/09/17 Python
python使用re模块爬取豆瓣Top250电影
2020/10/20 Python
python 装饰器重要在哪
2021/02/14 Python
浅谈css3中的渐进增强和优雅降级
2017/12/01 HTML / CSS
世界上最具创新性的增强型知名运动品牌:Proviz
2018/04/03 全球购物
惠普香港官方商店:HP香港
2019/04/30 全球购物
俄罗斯奢侈品牌衣服、鞋子和配饰的在线商店:INTERMODA
2020/07/17 全球购物
小学教师岗位职责
2013/11/25 职场文书
安全生产活动月方案
2014/03/09 职场文书
知识竞赛主持词
2014/03/26 职场文书
班委竞选演讲稿
2014/04/28 职场文书
护校行动方案
2014/05/31 职场文书
2014年小学教师工作总结
2014/11/10 职场文书
管理人员岗位职责
2015/02/14 职场文书
jdbc使用PreparedStatement批量插入数据的方法
2021/04/27 MySQL