文档章节

事物隔离级别和乐观锁

drv
 drv
发布于 2016/12/28 11:25
字数 926
阅读 3
收藏 0

  最近在迁移代码,迁移过程中发现了一段应用了乐观锁的代码(这是伪代码):

public boolean doWork(final int count, Entity entity) throws InterruptedException {
        if (3 == count) {
            return false;
        }
        int j = dao.update(entity);
        if (j == 0) {
            Thread.sleep(100);
            count++;
            Entity entity = dao.selectEntity(entity.id);
            return doWork(count, entity);
        } 
        return true;
    }

  大概意思是先执行更新。更新对应的表有一个version字段,entity的实例中是包含当前版本号的,更新时版本号匹配则返回true;如果不匹配则去数据库查询新的版本号,如果重试达到三次则报错。其实递归次数不多本来这也没什么问题,但是问题在于这段代码在一个事务中,而事务用的是默认的隔离级别,关键是数据库用的是mysql,和大多数数据库有点不一样,它用的默认隔离级别是可重复读(REPEATABLE_READ)。

  于是问题出现了,可重复读的隔离级别中,除非更新操作执行成功,否则同一个事务对同一条记录的读取返回总是一样的,也就是说,这个版本号如果出现不匹配,那后面三次重试一定不会成功,因为重新读出来的版本号就不是最新的,根本就没变:

  

  

  具体的测试代码在:https://github.com/saaavsaaa/warn-report/blob/master/src/test/java/DBTest.java。

  也就是说这个乐观锁白写了。。。

  其实乐观锁主要是应对并发问题,减少数据库的排队的手段,其实更多是应用在抛开事务的场景下来保证执行正确的。不过说并发其实也抗不了多少并发,就算不用事务,这种使用数据库去抗所有处理的方式。。。,其实我更喜欢用Redis解决类似情况,因为单线程、因为快、因为减少持久化存储的压力,数据库其实是互联网应用中相对最经不起故障的重要部分。将计数保存在Redis中,所有操作都只对Redis的值进行操作,发现Redis中无值,通知同步服务同步数据到Redis中,然后再计算服务从Redis取值计算,不过要注意同步服务需要判断Redis有值了,就不执行写操作了。 

  另外,降低隔离级别也可以解决这个用例的问题(其实读已提交级别是其他大多数数据库的默认隔离级别),下面方法仅供参考,上生产出问题不负责。。。,下面是读未提交的测试中默认5.6版本的库需要改的配置:http://www.cnblogs.com/saaav/p/5943393.html,spring当中有七种事务传播规则:PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。(两个事务互补干扰 各自管理各自的事务),可以对乐观锁方法使用这个配置,其他事务使用默认级别,降低风险,虽然我也不知道有什么风险,目前也没时间深入研究,但是数据库开发团队既然决定使用这个默认级别,应该是有什么原因。。。

  那个测试类里还有一个测试并发的方法testConcurrentUpdate,我机器配置一般,更新并发超过1100就有失败的了,1500的时候失败已经过半了,大部分是锁超时,不过并发写到这个程度一般也不会用数据库生抗了,所以细节就不说了,知道有这么个事就成了。

==========================================================

咱最近用的github:https://github.com/saaavsaaa

微信公众号:

转载请注明出处

© 著作权归作者所有

drv

drv

粉丝 2
博文 57
码字总数 75382
作品 0
东城
架构师
私信 提问
mysql事务和锁 SELECT FOR UPDATE

事务: 当然有的人用begin /begin work .推荐用START TRANSACTION 是SQL-99标准启动一个事务。 当用set autocommit = 0 的时候,你以后所有的sql都将作为事务处理,直到你用commit确认或 ro...

SibylY
2016/08/22
693
0
Hibernate事务与并发问题处理(乐观锁与悲观锁) [转]

Hibernate事务与并发问题处理(乐观锁与悲观锁) 一、数据库事务的定义   数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元...

祥子哥哥
2014/06/10
248
0
SQL Server中锁与事务隔离级别

SQL Server中的锁分为两类: 共享锁 排它锁 锁的兼容性:事务间锁的相互影响称为锁的兼容性。 SQL Server中可以锁定的资源包括:RID或键(行)、页、对象(如表)、数据库等等。 在试图修改数...

雪飞鸿
2018/07/15
0
0
Hibernate多事物并发访问控制

在并发环境,一个数据库系统会同时为各种各样的客户程序提供服务,也就是说,在同一时刻,会有多个客户程序同时访问数据库系统,这多个客户程序中的失误访问数据库中相同的数据时,如果没有采...

猴亮屏
2014/11/12
668
0
企业应用架构模式学习(五):并发

前言 本节并发讲解多用户同时访问同一个数据时,引起的数据不一致性,数据失效性,即我们开发中的事务处理以及版本控制。 并发问题 更新丢失(lost updates):当两个用户同时操作一条数据时...

大风起兮
2013/05/27
262
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
321
7
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
5
0
Spring Boot + Mybatis-Plus 集成与使用(二)

前言: 本章节介绍MyBatis-Puls的CRUD使用。在开始之前,先简单讲解下上章节关于Spring Boot是如何自动配置MyBatis-Plus。 一、自动配置 当Spring Boot应用从主方法main()启动后,首先加载S...

伴学编程
昨天
8
0
用最通俗的方法讲spring [一] ──── AOP

@[TOC](用最通俗的方法讲spring [一] ──── AOP) 写这个系列的目的(可以跳过不看) 自己写这个系列的目的,是因为自己是个比较笨的人,我曾一度怀疑自己的智商不适合干编程这个行业.因为在我...

小贼贼子
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部