浅谈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
基于PHP Web开发MVC框架的Smarty使用说明
Apr 19 PHP
CURL状态码列表(详细)
Jun 27 PHP
ThinkPHP之N方法实例详解
Jun 20 PHP
PHP中创建图像并绘制文字的例子
Nov 19 PHP
php中mysql操作buffer用法详解
Mar 19 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
Dec 10 PHP
php数值转换时间及时间转换数值用法示例
May 18 PHP
基于ThinkPHP5.0实现图片上传插件
Sep 25 PHP
Laravel timestamps 设置为unix时间戳的方法
Oct 11 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
Nov 24 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
Dec 01 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
基于Zend的Captcha机制的应用
2013/05/02 PHP
深入解析PHP内存管理之谁动了我的内存
2013/06/20 PHP
CentOS 安装 PHP5.5+Redis+XDebug+Nginx+MySQL全纪录
2015/03/25 PHP
PHP中list方法用法示例
2016/12/01 PHP
PHP7 弃用功能
2021/03/09 PHP
javascript 设置文本框中焦点的位置
2009/11/20 Javascript
分享精心挑选的12款优秀jQuery Ajax分页插件和教程
2012/08/09 Javascript
js用Date对象的setDate()函数对日期进行加减操作
2014/09/18 Javascript
javascript+html5实现仿flash滚动播放图片的方法
2015/04/27 Javascript
AngularJS 过滤器(自带和自建)详解
2016/09/19 Javascript
webpack常用配置项配置文件介绍
2016/11/07 Javascript
基于es6三点运算符的使用方法(实例讲解)
2017/10/12 Javascript
nodejs微信扫码支付功能实现
2018/02/17 NodeJs
nodejs连接mysql数据库及基本知识点详解
2018/03/20 NodeJs
Node.js 使用jade模板引擎的示例
2018/05/11 Javascript
通过jquery toggleClass()属性制作文章段落更改背景颜色
2018/05/21 jQuery
实例详解Node.js 函数
2018/06/10 Javascript
python3读取csv和xlsx文件的实例
2018/06/22 Python
Pycharm 2019 破解激活方法图文详解
2019/10/11 Python
Python 使用元类type创建类对象常见应用详解
2019/10/17 Python
Python jieba库分词模式实例用法
2021/01/13 Python
贝玲妃美国官方网站:Benefit美国
2016/08/28 全球购物
Liu Jo西班牙官网:意大利服装品牌
2019/09/11 全球购物
Araks官网:纽约内衣品牌
2020/10/15 全球购物
Yahoo-PHP面试题2
2014/12/06 面试题
您熟悉ORM(Object-Relation Mapping)吗?请谈谈您所理解的ORM
2016/02/08 面试题
大专毕业生求职信
2014/07/05 职场文书
4s店活动策划方案
2014/08/25 职场文书
殡葬服务心得体会
2014/09/11 职场文书
农村党支部书记党群众路线四风问题整改措施
2014/09/26 职场文书
2014年监理工作总结范文
2014/11/17 职场文书
个人年度总结报告
2015/03/09 职场文书
工程款催款函
2015/06/24 职场文书
七年级生物教学反思
2016/02/20 职场文书
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA
清空 Oracle 安装记录并重新安装
2022/04/26 Oracle