浅谈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 相关文章推荐
8个出色的WordPress SEO插件收集
Feb 26 PHP
Smarty的配置与高级缓存技术分享
Jun 05 PHP
深入PHP empty(),isset(),is_null()的实例测试详解
Jun 06 PHP
php实现执行某一操作时弹出确认、取消对话框
Dec 30 PHP
PHP登陆后跳转到登陆前页面实现思路及代码
Jan 17 PHP
测试php连接mysql是否成功的代码分享
Jan 24 PHP
php防止伪造的数据从URL提交方法
Jun 27 PHP
PHP中的Streams详细介绍
Nov 12 PHP
PHP统计数值数组中出现频率最多的10个数字的方法
Apr 20 PHP
php实现的美国50个州选择列表实例
Apr 20 PHP
php 如何获取文件的后缀名
Jun 05 PHP
php设计模式之单例模式用法经典示例分析
Sep 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
PHP实现设计模式中的抽象工厂模式详解
2014/10/11 PHP
PHP iconv()函数字符编码转换的问题讲解
2019/03/22 PHP
PHP快速导出百万级数据到CSV或者EXCEL文件
2020/11/27 PHP
原生js实现查找/添加/删除/指定元素的class
2013/04/12 Javascript
判断客户浏览器是否支持cookie的示例代码
2013/12/23 Javascript
JavaScript关闭当前页面(窗口)不带任何提示
2014/03/26 Javascript
nodejs爬虫抓取数据乱码问题总结
2015/07/03 NodeJs
如何实现json数据可视化详解
2016/11/24 Javascript
详解nodejs中express搭建权限管理系统
2017/09/15 NodeJs
vue使用 better-scroll的参数和方法详解
2018/01/25 Javascript
Vue在页面右上角实现可悬浮/隐藏的系统菜单
2018/05/04 Javascript
Vue数据双向绑定原理及简单实现方法
2018/05/18 Javascript
vue-cli3脚手架的配置及使用教程
2018/08/28 Javascript
微信小程序实现星星评价效果
2018/11/02 Javascript
详解vuex 渐进式教程实例代码
2018/11/27 Javascript
Vue实现页面添加水印功能
2019/11/09 Javascript
JavaScript交换两个变量方法实例
2019/11/25 Javascript
vue编写简单的购物车功能
2021/01/08 Vue.js
[06:43]2018DOTA2国际邀请赛寻真——VGJ.Thunder
2018/08/11 DOTA
浅谈Pandas中map, applymap and apply的区别
2018/04/10 Python
使用python 写一个静态服务(实战)
2019/06/28 Python
Kears+Opencv实现简单人脸识别
2019/08/28 Python
python输入一个水仙花数(三位数) 输出百位十位个位实例
2020/05/03 Python
python3获取控制台输入的数据的具体实例
2020/08/16 Python
Python字符串对齐、删除字符串不需要的内容以及格式化打印字符
2021/01/23 Python
html5构建触屏网站之网站尺寸探讨
2013/01/07 HTML / CSS
美国排名第一的在线葡萄酒商店:Wine.com
2016/09/07 全球购物
护士个人简历自荐信
2013/10/18 职场文书
优秀小学生家长评语
2014/01/30 职场文书
2014年社区综治工作总结
2014/11/17 职场文书
2014年化工厂工作总结
2014/11/25 职场文书
行为习惯主题班会
2015/08/14 职场文书
python实现简单反弹球游戏
2021/04/12 Python
浅谈Redis的几个过期策略
2021/05/27 Redis
python 对图片进行简单的处理
2021/06/23 Python
人民币符号
2022/02/17 杂记