浅谈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 04 PHP
PHP session常见问题集锦及解决办法总结
Mar 18 PHP
追求程序速度,而不是编程的速度
Apr 23 PHP
php的curl实现get和post的代码
Aug 23 PHP
PHP字符串函数系列之nl2br(),在字符串中的每个新行 (\n) 之前插入 HTML 换行符br
Nov 10 PHP
一个完整的PHP类包含的七种语法说明
Jun 04 PHP
yii2.0数据库迁移教程【多个数据库同时同步数据】
Oct 08 PHP
PHP CURL post数据报错 failed creating formpost data
Oct 16 PHP
php微信公众平台开发(四)回复功能开发
Dec 06 PHP
解析PHP之提取多维数组指定列的方法
Jan 03 PHP
PHP实现一维数组与二维数组去重功能示例
May 24 PHP
php封装的page分页类完整实例代码
Feb 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
兼容性最强的PHP生成缩略图的函数代码(修改版)
2011/01/18 PHP
php实例分享之通过递归实现删除目录下的所有文件详解
2014/05/15 PHP
PHP高精确度运算BC函数库实例详解
2017/08/15 PHP
php实现数字补零的方法总结
2018/09/12 PHP
基于jquery的不规则矩形的排列实现代码
2012/04/16 Javascript
jQuery获得子元素个数的方法
2015/04/14 Javascript
如何使用jQuery技术开发ios风格的页面导航菜单
2015/07/29 Javascript
Node.js操作Firebird数据库教程
2016/03/04 Javascript
jQuery中事件与动画的总结分享
2016/05/24 Javascript
Nodejs+express+ejs简单使用实例代码
2017/09/18 NodeJs
react中fetch之cors跨域请求的实现方法
2018/03/14 Javascript
微信小程序wx:for和wx:for-item的用法详解
2018/04/01 Javascript
深入理解react 组件类型及使用场景
2019/03/07 Javascript
基于vue-draggable 实现三级拖动排序效果
2020/01/10 Javascript
原生javascript的ajax请求及后台PHP响应操作示例
2020/02/24 Javascript
[40:01]OG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python中文件I/O高效操作处理的技巧分享
2017/02/04 Python
Python编程图形库之Pillow使用方法讲解
2018/12/28 Python
opencv python统计及绘制直方图的方法
2019/01/21 Python
python实现Excel文件转换为TXT文件
2019/04/28 Python
从numpy数组中取出满足条件的元素示例
2019/11/26 Python
opencv python在视屏上截图功能的实现
2020/03/05 Python
没编程基础可以学python吗
2020/06/17 Python
Django实现文章详情页面跳转代码实例
2020/09/16 Python
CSS3常用的几种颜色渐变模式总结
2016/11/18 HTML / CSS
UNIONBAY官网:美国青少年服装品牌
2019/03/26 全球购物
运动会解说词100字
2014/01/31 职场文书
大二学生职业生涯规划书
2014/02/05 职场文书
毕业生简历自我评价范文
2014/04/09 职场文书
水电维修专业推荐信
2014/09/06 职场文书
连锁超市项目计划书
2014/09/15 职场文书
考研导师推荐信范文
2015/03/27 职场文书
沂蒙六姐妹观后感
2015/06/08 职场文书
Java并发编程之原子性-Atomic的使用
2022/03/16 Java/Android
Docker官方工具docker-registry案例演示
2022/04/13 Servers
Redis数据同步之redis shake的实现方法
2022/04/21 Redis