浅谈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 md5下16位和32位的实现代码
Apr 09 PHP
采集邮箱的php代码(抓取网页中的邮箱地址)
Jul 17 PHP
PHP获取用户的浏览器与操作系统信息的代码
Sep 04 PHP
file_get_contents("php://input", "r")实例介绍
Jul 01 PHP
php实现mysql封装类示例
May 07 PHP
php实现事件监听与触发的方法
Nov 21 PHP
php站内搜索关键词变亮的实现方法
Dec 30 PHP
Win7下手动安装apache2.2、php5.4笔记
Apr 03 PHP
PHP动态生成指定大小随机图片的方法
Mar 25 PHP
PHP入门教程之使用Mysqli操作数据库的方法(连接,查询,事务回滚等)
Sep 11 PHP
利用switch语句进行多选一判断的实例代码
Nov 14 PHP
PHP7 其他修改
Mar 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
PHP的构造方法,析构方法和this关键字详细介绍
2013/10/22 PHP
php绘图中显示不出图片的原因及解决
2014/03/05 PHP
Zend Framework 2.0事件管理器(The EventManager)入门教程
2014/08/11 PHP
Yii中CGridView实现批量删除的方法
2015/12/28 PHP
php计算多个集合的笛卡尔积实例详解
2017/02/16 PHP
PHP排序算法之冒泡排序(Bubble Sort)实现方法详解
2018/04/20 PHP
浅谈php调用python文件
2019/03/29 PHP
Thinkphp5框架实现获取数据库数据到视图的方法
2019/08/14 PHP
初学JavaScript_03(ExtJs Grid的简单使用)
2008/10/02 Javascript
JS 参数传递的实际应用代码分析
2009/09/13 Javascript
javascript 清空form表单中某种元素的值
2009/12/26 Javascript
javascript中length属性的探索
2011/07/31 Javascript
JavaScript字符串对象slice方法入门实例(用于字符串截取)
2014/10/16 Javascript
javascript实现禁止右键和F12查看源代码
2014/12/26 Javascript
JS创建对象几种不同方法详解
2016/03/01 Javascript
微信小程序实现城市列表选择
2018/06/05 Javascript
基于vue-router 多级路由redirect 重定向的问题
2018/09/03 Javascript
webpack4+react多页面架构的实现
2018/10/25 Javascript
vue文件运行的方法教学
2019/02/12 Javascript
layer ui 导入文件之前传入数据的实例
2019/09/23 Javascript
vue和H5 draggable实现拖拽并替换效果
2020/07/29 Javascript
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
python实现文件名批量替换和内容替换
2014/03/20 Python
详细介绍Python的鸭子类型
2016/09/12 Python
用Python下载一个网页保存为本地的HTML文件实例
2018/05/21 Python
Python数据类型之List列表实例详解
2019/05/08 Python
Python中Numpy ndarray的使用详解
2019/05/24 Python
HTML5组件Canvas实现图像灰度化(步骤+实例效果)
2013/04/22 HTML / CSS
英国家庭和商业健身器材购物网站:Fitness Options
2018/07/05 全球购物
linux面试题参考答案(5)
2014/09/01 面试题
食品科学与工程专业毕业生求职信范文
2014/07/21 职场文书
幸福来敲门观后感
2015/06/04 职场文书
新手开公司创业注意事项有哪些?
2019/07/29 职场文书
详解CSS不受控制的position fixed
2021/05/25 HTML / CSS
浅谈Web Storage API的使用
2021/06/23 Javascript
mysq启动失败问题及场景分析
2021/07/15 MySQL