用MySQL的默认隔离级别,可重复读,采用version=1,2,3,4.....来实现乐观锁的,当两个线程A,B同时操作数据库的一行记录,如果都是先开启事务,然后都是先查询出数据,比如说如下A,B来个线程查询结果如下:
Table :person
A:id name version
1 tom 1 B:id name version
1 tom 1
此时A线程先开更新数据
update set name='jack' ,version =version+1 where id=1 and version =1
然后A线程提交事务。
然后B线程也要更新name的值,但是此时的B线程在查询select * from person
得到的结果肯定是
B:id name version
1 tom 1 此时如果B也要更新name的值,那么B线程要获取version的值是如何获取的呢,通过查询肯定不行,因为查询结果如上,那么是在java代码里面把每次更新过后的version值通过方法的参数传递给B线程吗。即我们在控制version都是通过java代码来获取version的值,而不是通过在数据库中查询相应的version值吗。在网上查的资料都是笼统的说,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,但是如何获取更新过后的version还是没有说明白。请教大神
Table :person
A:id name version
1 tom 1 B:id name version
1 tom 1
此时A线程先开更新数据
update set name='jack' ,version =version+1 where id=1 and version =1
然后A线程提交事务。
然后B线程也要更新name的值,但是此时的B线程在查询select * from person
得到的结果肯定是
B:id name version
1 tom 1 此时如果B也要更新name的值,那么B线程要获取version的值是如何获取的呢,通过查询肯定不行,因为查询结果如上,那么是在java代码里面把每次更新过后的version值通过方法的参数传递给B线程吗。即我们在控制version都是通过java代码来获取version的值,而不是通过在数据库中查询相应的version值吗。在网上查的资料都是笼统的说,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,但是如何获取更新过后的version还是没有说明白。请教大神
解决方案 »
- 最近工作比较闲,想研究下算法。大家给点意见。
- 怎么实现鼠标点到哪里图片就到哪里
- 请教高手:线程池捕获异常的问题
- 多用户实例化和使用JavaBeans 会冲突吗???
- jsp页面怎么访问外部类?
- 求oracle中建用户表空间,
- 高分求救:连接oracle的记录集产生ORA-01009: 缺少法定参数的错误!
- 求助:如何通过按钮在text的指定处添加字符串?
- 请问:那里可以找到文档编排的JSP源码?
- 请问哪有支持jsp的免费主页空间?谢谢
- javaWeb项目如何实现下载2G的文件下载,并保存至指定的Windows文件jia
- ssh整合项目出错,dao的查询总是包空指针错误,找了好久不知道问题在哪。。
如果A提交了事务,B检索出的结果就不应该是这样,应该是version=2
除非你的每个线程的检索结果都用了缓存,那么A提交事务的时侯就应该刷新缓存
此时你只需判断B最开始取出来的version和A提交事务后再取出来的version是否一致,如果一致B就提交事务,否则做相应的排他处理,这就是所谓的乐观排他
我的问题是:如果B用户要继续修改,那怎么保证B重新获取的数据是最新的,就是实现方式。
我的
1.假设A,B用户在开启事务后,获取的数据是一致的,A先修改数据,然后提交事务。B在修改数据,那么就会报错,即修改不成功。
2.那么我理解的B获取数据是最新的,是这样产生的,在A用户提交事务之后,B在开启事务,然后获取数据,这个数据应该是最新的。
也就是A用户事务提交之后,B事务在开始,然后获取的数据就是最新的。
此时B重新取得的数据一定是最新的,除非你用了缓存,那你应该在提交事务时有个刷新缓存的操作
或者你用个触发器来控制,在提交事务的时候比较version,不一致的是否就拒否
我的问题是:如果B用户要继续修改,那怎么保证B重新获取的数据是最新的,就是实现方式。
我的
1.假设A,B用户在开启事务后,获取的数据是一致的,A先修改数据,然后提交事务。B在修改数据,那么就会报错,即修改不成功。
2.那么我理解的B获取数据是最新的,是这样产生的,在A用户提交事务之后,B在开启事务,然后获取数据,这个数据应该是最新的。
也就是A用户事务提交之后,B事务在开始,然后获取的数据就是最新的。可以按照假设1来继续展开,如果B修改报错,重试,可以设定重试次数.具体可以参考:
https://nanjiwubing123.iteye.com/blog/2261394
在阿里JAVA开发手册中也有这样的约定:
8. 【强制】并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据。 说明:如果每次访问冲突概率小于20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于3次。