浅谈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
基于asp+ajax和数据库驱动的二级联动菜单
May 06 PHP
简单的php写入数据库类代码分享
Jul 26 PHP
php中的strpos使用示例
Feb 27 PHP
php获取中文拼音首字母类和函数分享
Apr 24 PHP
Apache连接PHP后无法启动问题解决思路
Jun 18 PHP
使用PHP免费发送定时短信的实例
Oct 24 PHP
PHP实现的简单AES加密解密算法实例
May 29 PHP
浅析PHP数据导出知识点
Feb 17 PHP
php ajax confirm 删除实例详解
Mar 06 PHP
php curl操作API接口类完整示例
May 21 PHP
关于Anemometer图形化显示MySQL慢日志的工具搭建及使用的详细介绍
Jul 13 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
ThinkPHP字符串函数及常用函数汇总
2014/07/18 PHP
php通过baihui网API实现读取word文档并展示
2015/06/22 PHP
整理php防注入和XSS攻击通用过滤
2015/09/13 PHP
XHProf报告字段含义的解析
2016/05/17 PHP
微信公众平台开发教程③ PHP实现微信公众号支付功能图文详解
2019/04/10 PHP
JS getStyle获取最终样式函数代码
2010/04/01 Javascript
javascript基础第一章 JavaScript与用户端
2010/07/22 Javascript
30个最佳jQuery Lightbox效果插件分享
2011/04/11 Javascript
JS函数实现动态添加CSS样式表文件
2012/12/15 Javascript
jQuery响应enter键的实现思路
2014/04/18 Javascript
jQuery超赞的评分插件(8款)
2015/08/20 Javascript
Javascript模仿淘宝信用评价实例(附源码)
2015/11/26 Javascript
基于vue实现swipe轮播组件实例代码
2017/05/24 Javascript
React.Js添加与删除onScroll事件的方法详解
2017/11/03 Javascript
如何让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)
2019/05/30 NodeJs
[04:00]DOTA2解说界神雕侠侣 CJ第四天谷子现场过生日
2013/07/30 DOTA
python计算书页码的统计数字问题实例
2014/09/26 Python
python内存管理分析
2015/04/08 Python
Python中datetime常用时间处理方法
2015/06/15 Python
在Python中os.fork()产生子进程的例子
2019/08/08 Python
Python自动化导出zabbix数据并发邮件脚本
2019/08/16 Python
Python3爬虫里关于识别微博宫格验证码的知识点详解
2020/07/30 Python
Python 删除List元素的三种方法remove、pop、del
2020/11/16 Python
CSS3实现翘边的阴影效果的代码示例
2016/06/13 HTML / CSS
CSS3模拟动画下拉菜单效果
2017/04/12 HTML / CSS
德国亚马逊官方网站:Amazon.de
2020/11/15 全球购物
物流专业毕业生推荐信范文
2013/11/18 职场文书
中学生班主任评语
2014/01/30 职场文书
党风廉政承诺书
2014/03/27 职场文书
购房协议书范本(无房产证)
2014/10/07 职场文书
优秀班主任申报材料
2014/12/16 职场文书
汉语拼音教学反思
2016/02/22 职场文书
2019个人工作自我评价范文(3篇)
2019/09/19 职场文书
python实现商品进销存管理系统
2022/05/30 Python
使用CSS实现黑白格背景效果
2022/06/01 HTML / CSS
webpack介绍使用配置教程详解webpack介绍和使用
2022/06/25 Javascript