mysql乐观锁实现_mysql实现乐观锁实例(demo)
本文参考:https://blog.csdn.net/seapeak007/article/details/53490156,感谢老铁的辛苦付出。
乐观锁介绍:
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。那么我们如何实现乐观锁呢,一般来说有以下2种方式:
1.使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。用下面的一张图来说明:
如上图所示,如果更新操作顺序执行,则数据的版本(version)依次递增,不会产生冲突。但是如果发生有不同的业务操作对同一版本的数据进行修改,那么,先提交的操作(图中B)会把数据version更新为2,当A在B之后提交更新时发现数据的version已经被修改了,那么A的更新操作会失败。
2.乐观锁定的第二种实现方式和第一种差不多,同样是在需要乐观锁控制的table中增加一个字段,名称无所谓,字段类型使用时间戳(timestamp), 和上面的version类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。
使用举例:以MySQL InnoDB为例
还是拿之前的实例来举:商品goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。
下单操作包括3步骤:
1.查询出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根据商品信息生成订单
3.修改商品status为2
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
那么为了使用乐观锁,我们首先修改t_goods表,增加一个version字段,数据默认version值为1。
t_goods表初始数据如下:
Sql代码
mysql> select * from t_goods;
+----+--------+------+---------+
| id | status | name | version |
+----+--------+------+---------+
| 1 | 1 | 道具 | 1 |
| 2 | 2 | 装备 | 2 |
+----+--------+------+---------+
2 rows in set
mysql>
对于乐观锁的实现,我使用MyBatis来进行实践,具体如下:
Goods实体类:
Java代码
/**
* ClassName: Goods
* Function: 商品实体.
* date: 2013-5-8 上午09:16:19
* @author chenzhou1025@126.com
*/
public class Goods implements Serializable {
/**
* serialVersionUID:序列化ID.
*/
private static final long serialVersionUID = 6803791908148880587L;
/**
* id:主键id.
*/
private int id;
/**
* status:商品状态:1未下单、2已下单.
*/
private int status;
/**
* name:商品名称.
*/
private String name;
/**
* version:商品数据版本号.
*/
private int version;
@Override
public String toString(){
return "good id:"+id+",goods status:"+status+",goods name:"+name+",goods version:"+version;
}
//setter and getter
}
GoodsDao
Java代码
/**
* updateGoodsUseCAS:使用CAS(Compare and set)更新商品信息.
*
* @author chenzhou1025@126.com
* @param goods 商品对象
* @return 影响的行数
*/
int updateGoodsUseCAS(Goods goods);
mapper.xml
Xml代码
update t_goods
set status=#{status},name=#{name},version=version+1
where id=#{id} and version=#{version}
]]>
GoodsDaoTest测试类
Java代码
@Test
public void goodsDaoTest(){
int goodsId = 1;
//根据相同的id查询出商品信息,赋给2个对象
Goods goods1 = this.goodsDao.getGoodsById(goodsId);
Goods goods2 = this.goodsDao.getGoodsById(goodsId);
//打印当前商品信息
System.out.println(goods1);
System.out.println(goods2);
//更新商品信息1
goods1.setStatus(2);//修改status为2
int updateResult1 = this.goodsDao.updateGoodsUseCAS(goods1);
System.out.println("修改商品信息1"+(updateResult1==1?"成功":"失败"));
//更新商品信息2
goods1.setStatus(2);//修改status为2
int updateResult2 = this.goodsDao.updateGoodsUseCAS(goods1);
System.out.println("修改商品信息2"+(updateResult2==1?"成功":"失败"));
}
输出结果:
Shell代码
good id:1,goods status:1,goods name:道具,goods version:1
good id:1,goods status:1,goods name:道具,goods version:1
修改商品信息1成功
修改商品信息2失败
(因为两个对象goods1 goods2都是获取到的同一个id的对象,对象中的version一样,所以更新了一个后,sersion值不同了,goods2更新失败了)
说明:
在GoodsDaoTest测试方法中,我们同时查出同一个版本的数据,赋给不同的goods对象,然后先修改good1对象然后执行更新操作,执行成功。然后我们修改goods2,执行更新操作时提示操作失败。此时t_goods表中数据如下:
Sql代码
mysql> select * from t_goods;
+----+--------+------+---------+
| id | status | name | version |
+----+--------+------+---------+
| 1 | 2 | 道具 | 2 |
| 2 | 2 | 装备 | 2 |
+----+--------+------+---------+
2 rows in set
mysql>
我们可以看到 id为1的数据version已经在第一次更新时修改为2了。所以我们更新good2时update where条件已经不匹配了,所以更新不会成功,具体sql如下:
Sql代码
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
这样我们就实现了乐观锁
mysql乐观锁实现_mysql实现乐观锁实例(demo)相关推荐
- mysql乐观和悲观锁实现_mysql实现乐观锁和悲观锁该怎么编写?
乐观锁和悲观锁相信大家都是知道的,这是java中的基础知识,今天我们就来看看它们两者该如何使用代码实现吧. 乐观锁实现 1).表设计 表task,分别有三个字段id,value.version 2). ...
- mysql 悲观锁 性能_mysql的乐观锁和悲观锁
悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念.本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍. 悲观锁(Pessimistic Lock) 悲观锁的 ...
- mysql乐观锁效果_MySQL的乐观锁
一.乐观锁介绍 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检查,乐观锁适用 ...
- mysql记录锁与互斥锁区别_MySQL的各种锁认知
一.相关名词 |--表级锁(锁定整个表) |--页级锁(锁定一页) |--行级锁(锁定一行) |--共享锁(S锁,MyISAM 叫做读锁) |--排他锁(X锁,MyISAM 叫做写锁) |--悲观锁( ...
- MySQL并发 共享锁目的_mysql并发与锁机制
在InnoDB中,锁是逐步获得的,因此发生死锁是可能的.发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并回退,另外一个事务获得锁,并继续完成事务.但在涉及外部锁,或涉及表锁的情况下,I ...
- mysql某个表被行锁了_MySQL中的锁(表锁、行锁)
锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数 ...
- mysql 并发 锁表_MySQL中的锁(表锁、行锁) 并发控制锁
https://github.com/MrLining/mysql/wiki/MySQL%E4%B8%AD%E7%9A%84%E9%94%81%EF%BC%88%E8%A1%A8%E9%94%81%E ...
- mysql 锁 代码_MySQL中的锁实例
表结构: id:自增主键,a:无索引,b:普通索引 CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` int(4) NOT ...
- mysql 页级锁写法_MYSQL中表级锁、行级锁、页级锁介绍
一.MYSQL数据库锁的种类 在数据库系统中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM引擎)和页级锁(BDB引擎 ). 1.行级锁 行级锁是Mysql中锁定粒度最 ...
最新文章
- python爬虫教程i-Python 爬虫速成教程,还有35个实战项目送给你!
- url,html,javascript中的转义字符
- 基于nginx实现minio分布式集群访问的负载均衡配置示例
- Windows 7可以体验IE10了
- oracleDBA-D1
- 克隆需要验证_[实验技巧]CRISPR实验中如何验证编辑?
- kindeditor编辑器图片上传session丢失_微信公众号排版编辑器全指南!
- Android应用程序文件缓存getCacheDir()和getExternalCacheDir()
- 帮助新手理解equals和hashCode
- iOS.数据持久化.PersistenceLayer.属性列表
- ACL访问控制 getfacl 、setfacl 命令
- hdu2586 lca倍增法
- NEWSCTF第二届--官方wp(2021.6.1萌新赛)
- javascript毫秒计时器_JavaScript原生秒表、计时器
- 你们制作微信表情包都用了哪些软件?当然必备这3款
- QQ聊天记录多角度分析Python实现
- 柴静《看见》发布会。。。
- 牙林一中2021年高考成绩查询,牙林一中2019高考成绩喜报、一本二本上线人数情况...
- Java中String使用及分析(UTF-8简单编码/解码器实现)
- 软考系统集成项目管理工程师模拟题
热门文章
- PWM模式与极性谈论
- SAP SD之发货和运输
- 简单介绍单片机、电脑处理器原理
- windows 安装Chocolatey
- 《Context Aware Query Image Representation for Particular Object Retrieval》论文阅读
- WindowsMouseEvent鼠标模拟事件
- postman断言详解
- Java基础编程题目——接口应用,display()函数显示消息
- PLSQL中文显示乱码,真正有效的解决方案(无需修改注册表 )
- “十年内难以落地”的无人驾驶,第一站会在哪里?