乐观锁
2015-06-21 17:01
295 查看
1.使用原因
实际上是为了解决数据库并发访问的情况。
如一个银行账户中余额为1000元,A向其中转账200,B从中取出300,那么应该是剩余900,。
但实际情况下,可能是A转了200,但是还没有提交事务,这个时候B获取余额信息,值是1000,取出300后,修改余额为700,提交事务,然后A又提交事务,这时候账户余额变为1200,显然是不对的。
这个时候就需要一种机制来保证,同一时间只有一个事务能操作这条数据,这个时候就可以使用乐观锁
2.实现
(1)使用version字段
在数据库表中添加一个数字类型的version字段。当读取数据库时,讲version字段的值一起读出,数据每更新一次,对此version+1.当我们提交更新的时候,判断数据库表中记录的version字段与之前读出的version的值是否相同,如果相同,就说明期间没有被其他事务修改,可以更新;如果不相同,说明已经是过期数据了,不能更新
(2)使用更新时间
在数据库表中定义一个更新时间,也是在提交的时候比较当前数据库中的数据的时间和自己取到的时间是否相同,如果一致则可以更新,否则就是版本冲突
3.实例
(1)数据库表
(2)数据库操作(此处ibatis+spring实现)
(3)测试
modified success!
has been modified!
4.注意
使用乐观锁的时候,是否记录已经被更改是通过update的返回值来确定的!
实际上是为了解决数据库并发访问的情况。
如一个银行账户中余额为1000元,A向其中转账200,B从中取出300,那么应该是剩余900,。
但实际情况下,可能是A转了200,但是还没有提交事务,这个时候B获取余额信息,值是1000,取出300后,修改余额为700,提交事务,然后A又提交事务,这时候账户余额变为1200,显然是不对的。
这个时候就需要一种机制来保证,同一时间只有一个事务能操作这条数据,这个时候就可以使用乐观锁
2.实现
(1)使用version字段
在数据库表中添加一个数字类型的version字段。当读取数据库时,讲version字段的值一起读出,数据每更新一次,对此version+1.当我们提交更新的时候,判断数据库表中记录的version字段与之前读出的version的值是否相同,如果相同,就说明期间没有被其他事务修改,可以更新;如果不相同,说明已经是过期数据了,不能更新
(2)使用更新时间
在数据库表中定义一个更新时间,也是在提交的时候比较当前数据库中的数据的时间和自己取到的时间是否相同,如果一致则可以更新,否则就是版本冲突
3.实例
(1)数据库表
(2)数据库操作(此处ibatis+spring实现)
public Integer updatePersonCAS(Person person) { return getSqlMapClientTemplate().update("person.updatePersonCAS", person); }sql
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" > <sqlMap namespace="person"> <!-- 使用别名可以避免每次都输入类路径全称 --> <typeAlias alias="Person" type="com.mycompany.app.dataObject.Person"/> <resultMap id="PersonResult" class="Person" > <result property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="version" column="version"/> </resultMap> <update id="updatePersonCAS" parameterClass="Person" > update person set name=#name# ,version=version+1 where id=#id# and version=#version# </update> <!-- 根据id查询用户信息 --> <select id="selectPersonById" parameterClass="java.lang.Integer" resultClass="Person"> SELECT * FROM person WHERE ID=#id# </select> <sqlMap>
(3)测试
@Test public void testUpdatePersonCAS() { Person person = personDAO.selectById(1); person.setName("cas"); Integer res = personDAO.updatePersonCAS(person); if (res!=1) { System.out.println("has been modified!"); } else { System.out.println("modified success!"); } person.setName("cas2"); Integer res2 = personDAO.updatePersonCAS(person); if (res2!=1) { System.out.println("has been modified!"); } else { System.out.println("modified success!"); } }结果为:
modified success!
has been modified!
4.注意
使用乐观锁的时候,是否记录已经被更改是通过update的返回值来确定的!
相关文章推荐
- C++ 文件逐行读入 并按空格分割
- Android Material Design之Toolbar与Palette实践
- 多线程 基本概念
- 在Oracle 10g 中如何以sys的身份登录isqlplus页面
- Centos zabbix 编译安装
- Single Number
- Linux内核(四)系统调用
- 第十五周oj刷题——Problem I: C++ 习题 比较大小-类模板
- 第十六周阅读程序(3)
- iOS笔记052- Quartz2D-绘图
- 表单选择器
- android ListView详解
- 研一总结
- 20150621针对AVAudioPlayer模拟器上没有播放声音
- 银联卡现金转账类业务规则
- Node.Js的Module System 以及一些常用 Module
- PHP打印指定日期
- leetcode_25题——Reverse Nodes in k-Group (链表)
- Linux内核(三)进程调度
- 【LeetCode】Rotate Array