浅谈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.ini中文版(2)
Oct 09 PHP
PHP 中文乱码解决办法总结分析
Jul 30 PHP
php imagecreatetruecolor 创建高清和透明图片代码小结
May 15 PHP
浅析十款PHP开发框架的对比
Jul 05 PHP
php通过数组实现多条件查询实现方法(字符串分割)
May 06 PHP
php实现微信公众平台账号自定义菜单类
Oct 11 PHP
twig模板常用语句实例小结
Feb 04 PHP
php好代码风格的阶段性总结
Jun 25 PHP
PHP生成word文档的三种实现方式
Nov 14 PHP
laravel框架中路由设置,路由参数和路由命名实例分析
Nov 23 PHP
phpstudy后门rce批量利用脚本的实现
Dec 12 PHP
Nginx+php配置文件及原理解析
Dec 09 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
Smarty缓存机制实例详解【三种缓存方式】
2019/07/20 PHP
jQuery使用手册之一
2007/03/24 Javascript
判断多个元素(RADIO,CHECKBOX等)是否被选择的原理说明
2009/02/18 Javascript
JavaScript Event学习第二章 Event浏览器兼容性
2010/02/07 Javascript
指定区域的图片自动按比例缩小的js代码(防止页面被图片撑破)
2014/02/21 Javascript
关于onchange事件在IE和FF下的表现及解决方法
2014/03/08 Javascript
单元选择合并变色示例代码
2014/05/26 Javascript
JS实现仿FLASH效果的竖排导航代码
2015/09/15 Javascript
jQuery实现简单的计时器功能实例分析
2017/08/29 jQuery
防止页面url缓存中ajax中post请求的处理方法
2017/10/10 Javascript
vue解决跨域路由冲突问题思路解析
2017/11/03 Javascript
Vue页面骨架屏注入方法
2018/05/13 Javascript
微信小程序实现tab左右切换效果
2020/11/15 Javascript
写gulp遇到的ES6问题详解
2018/12/03 Javascript
Vue的状态管理vuex使用方法详解
2020/02/05 Javascript
python检测某个变量是否有定义的方法
2015/05/20 Python
Python编程修改MP3文件名称的方法
2017/04/19 Python
Python 12306抢火车票脚本 Python京东抢手机脚本
2018/02/06 Python
python实现微信发送邮件关闭电脑功能
2018/02/22 Python
python字符串替换第一个字符串的方法
2019/06/26 Python
Python selenium 自动化脚本打包成一个exe文件(推荐)
2020/01/14 Python
解决pycharm编辑区显示yaml文件层级结构遇中文乱码问题
2020/04/27 Python
基于Python-Pycharm实现的猴子摘桃小游戏(源代码)
2021/02/20 Python
CSS3 完美实现圆角效果
2009/07/13 HTML / CSS
在IE6系列等老式浏览器中使用HTML5的新标签实现方案
2012/12/25 HTML / CSS
详解HTML5 data-* 自定义属性
2018/01/24 HTML / CSS
意大利奢华内衣制造商:Cosabella
2017/08/29 全球购物
韩语专业本科生求职信
2013/10/01 职场文书
美术国培研修感言
2014/02/12 职场文书
服装促销活动方案
2014/02/23 职场文书
学校班子个人对照检查材料思想汇报
2014/09/27 职场文书
百年孤独读书笔记
2015/06/29 职场文书
趣味运动会赞词
2015/07/22 职场文书
python 模拟在天空中放风筝的示例代码
2021/04/21 Python
jupyter notebook保存文件默认路径更改方法汇总(亲测可以)
2021/06/09 Python
css3带你实现3D转换效果
2022/02/24 HTML / CSS