浅谈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 小乘法表实现代码
Jul 16 PHP
php自动加载机制的深入分析
Jun 08 PHP
关于使用coreseek并为其做分页的介绍
Jun 21 PHP
检查用户名是否已在mysql中存在的php写法
Jan 20 PHP
php基于双向循环队列实现历史记录的前进后退等功能
Aug 08 PHP
WordPress中调试缩略图的相关PHP函数使用解析
Jan 07 PHP
ThinkPHP实现更新数据实例详解(demo)
Jun 29 PHP
php+ajax简单实现全选删除的方法
Dec 06 PHP
Symfony查询方法实例小结
Jun 28 PHP
laravel如何开启跨域功能示例详解
Aug 31 PHP
YII框架页面缓存操作示例
Apr 29 PHP
PHP执行linux命令6个函数代码实例
Nov 24 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增删改查示例自己写的demo
2013/09/04 PHP
PHP实现实时生成并下载超大数据量的EXCEL文件详解
2017/10/23 PHP
php 使用expat方式解析xml文件操作示例
2019/11/26 PHP
网站繁简切换的JS遇到页面卡死的解决方法
2014/03/12 Javascript
javascript实现俄罗斯方块游戏的思路和方法
2015/04/27 Javascript
javascript中对变量类型的判断方法
2015/08/09 Javascript
Bootstrap前端开发案例一
2016/06/17 Javascript
你真的了解BOM中的history对象吗
2017/02/13 Javascript
详解在vue-cli项目中安装node-sass
2017/06/21 Javascript
详解如何用webpack打包一个网站应用项目
2017/07/12 Javascript
菊花转动的jquery加载动画效果
2018/08/19 jQuery
js设计模式之代理模式及订阅发布模式实例详解
2019/08/15 Javascript
JavaScript JSON数据处理全集(小结)
2019/08/15 Javascript
Paypal支付不完全指北
2020/06/04 Javascript
[01:01:24]DOTA2上海特级锦标赛A组败者赛 EHOME VS CDEC第三局
2016/02/25 DOTA
[50:20]DOTA2上海特级锦标赛主赛事日 - 5 总决赛Liquid VS Secret第四局
2016/03/06 DOTA
python教程之用py2exe将PY文件转成EXE文件
2014/06/12 Python
Python读取网页内容的方法
2015/07/30 Python
Python数据可视化教程之Matplotlib实现各种图表实例
2019/01/13 Python
python tkinter canvas 显示图片的示例
2019/06/13 Python
Django Rest framework三种分页方式详解
2019/07/26 Python
PyQt5基本控件使用详解:单选按钮、复选框、下拉框
2019/08/05 Python
python中设置超时跳过,超时退出的方式
2019/12/13 Python
python 通过邮件控制实现远程控制电脑操作
2020/03/16 Python
Python request操作步骤及代码实例
2020/04/13 Python
在终端启动Python时报错的解决方案
2020/11/20 Python
css3闪亮进度条效果实现思路及代码
2013/04/17 HTML / CSS
使用html5制作loading图的示例
2014/04/14 HTML / CSS
HTML5页面直接调用百度地图API获取当前位置直接导航目的地的实现代码
2018/03/02 HTML / CSS
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
市场营销职业生涯规划书范文
2014/01/12 职场文书
运动会解说词50字
2014/01/18 职场文书
2014年保险公司工作总结
2014/11/22 职场文书
2016年党员公开承诺书格式范文
2016/03/24 职场文书
Python打包exe时各种异常处理方案总结
2021/05/18 Python
SQL Server数据库备份和恢复数据库的全过程
2022/06/14 SQL Server