Spring事务隔离级别简介及实例解析

 更新时间:2018年02月05日 15:26:17   作者:CupOnDesk  
这篇文章主要介绍了Spring事务隔离级别简介及实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

本文研究的主要是Spring事务隔离级别(solation level)介绍及例子,具体如下。

当两个事务对同一个数据库的记录进行操作时,那么,他们之间的影响是怎么样的呢?这就出现了事务隔离级别的概念。数据库的隔离性与并发控制有很大关系。数据库的隔离级别是数据库的事务特性ACID的一部分。ACID,即原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。Spring的事务隔离级别有四个:READ_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE。还有一个,是数据库默认的隔离级别DEFAULT,MySQL默认是REPEATABLE_READ

下面来具体看看。

READ_UNCOMMITTED

顾名思义,READ_UNCOMMITTED意思是,一个事务可以读取到另一个事务未提交的事务记录。换句话说,a transaction can read the data that is still uncommitted by other transactions。这是Spring事务最弱的隔离级别。见下面的图,事务A开启,写入一条记录,这时候,事务B读入数据,读到了这条记录,但是,之后事务A回滚。因此,事务B读到的数据不是有效的(the database is in an invalid state)。这种情况称为脏读(dirty read)。除了脏读的问题,READ_UNCOMMITTED还可能出现non-repeatable read(不可重复读)和phantom read(幻读)的问题。

READ_COMMITTED

READ_COMMITTED隔离级别表明,一个事务只能读取到已经提交的记录,不能读取到未提交的记录。换句话说,a transaction can only read the committed data, and it can't read the uncommitted data.因此,dirty read的情况不再发生,但可能会出现其他问题。见下图。

在事务A两次读取的过程之间,事务B修改了那条记录并进行提交。因此,事务A前后两次读取的记录不一致。这个问题称为non-repeatable read(不可重复读)。(两次读取的记录不一致,重复读取就会发现问题。)

除了non-repeatable read的问题,READ_COMMITTED还可能发生phantom read的问题。

REPEATABLE_READ

REPEATABLE_READ意思是,一个事务可以多次从数据库读取某条记录,而且多次读取的那条记录都是一致的,相同的。这个隔离级别可以避免dirty read和non-repeatable read的问题,但可能发生phantom read的问题。如下图。

事务A两次从数据库读取一系列记录,期间,事务B插入了某条记录并提交。事务A第二次读取时,会读取到事务B刚刚插入的那条记录。在事务期间,事务A两次读取的一系列记录不一致,这个问题称为phantom read。

SERIALIZABLE

SERIALIZABLE是Spring最强的隔离级别。事务执行时,会在所有级别上加锁,比如read和write时都会加锁,仿佛事务是以串行的方式进行的,而不是一起发生的。这会防止dirty read、non-repeatable read和phantom read的出现,但是,会带来性能的下降。

DEFAULT

MySQL默认是REPEATABLE_READ

例子

下面,我们看一个例子。在数据库mysql里开启一个事务,不提交。然后,另一个事务读取记录。

刚开始,数据库里的记录,如图

接下来,在数据库mysql中开启事务A,并插入一条记录。

在service的业务类的事务属性配置为READ_UNCOMMITTED

@Transactional(isolation=Isolation.READ_UNCOMMITTED)
public class AccountService {
	private AccountDAO accountDAO;
	public AccountDAO getAccountDAO() {
		return accountDAO;
	}
	public void setAccountDAO(AccountDAO accountDAO) {
		this.accountDAO = accountDAO;
	}
	public void transfer(String from, String to, double money) {
		accountDAO.outMoney(from, money);
		accountDAO.inMoney(to, money);
	}
	public void readAllUser() {
		List<Account> accounts = accountDAO.getAllUser();
		for (Account account : accounts) {
			System.out.println(account);
		}
	}
}

运行下面的测试类

package com.chris.service;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class ReadAllUserTest {
	@Autowired
	  private AccountService accountService;
	@Test
	  public void test() {
		accountService.readAllUser();
	}
}

结果如下:

可见,这个事务读取到了未提交的数据。

这时候,将mysql中开启的事务A回滚。

mysql> rollback;

再次运行程序,结果为

Account [name=Michael, money=1000.0]
Account [name=Jane, money=1000.0]
Account [name=Kate, money=1000.0]

总结

以上就是本文关于Spring事务隔离级别简介及实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

相关文章

  • SpringBoot实现分页功能

    SpringBoot实现分页功能

    这篇文章主要为大家详细介绍了SpringBoot实现分页功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 如何利用JAVA实现走迷宫程序

    如何利用JAVA实现走迷宫程序

    最近经常在机房看同学在玩一个走迷宫的游戏,比较有趣,自己也用java实现了一个,这篇文章主要给大家介绍了关于如何利用JAVA实现走迷宫程序的相关资料,需要的朋友可以参考下
    2021-06-06
  • springboot实现异步调用@Async的示例

    springboot实现异步调用@Async的示例

    这篇文章主要介绍了springboot实现异步调用@Async的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Java图片处理之获取gif图一帧图片的两种方法

    Java图片处理之获取gif图一帧图片的两种方法

    这篇文章主要给大家介绍了关于Java图片处理之获取gif图一帧图片的两种方法,分别是利用Java原生代码和使用im4java调用ImageMagick来实现,两种方法都给出来示例代码供大家参考学习,需要的朋友们下面来一起看看吧。
    2017-10-10
  • 基于MockMvc进行springboot调试(SpringbootTest)

    基于MockMvc进行springboot调试(SpringbootTest)

    这篇文章主要介绍了基于MockMvc进行springboot调试(SpringbootTest),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Java实现将每日新闻添加到自己博客中

    Java实现将每日新闻添加到自己博客中

    这篇文章主要为大家详细介绍了Java如何实现将每日新闻添加到自己博客中并发送到微信群中,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-12-12
  • Spring Boot使用AOP在指定方法执行完后执行异步处理操作

    Spring Boot使用AOP在指定方法执行完后执行异步处理操作

    这篇文章主要介绍了Spring Boot使用AOP在指定方法执行完后执行异步处理操作,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • SpringBoot结合SpringSecurity实现图形验证码功能

    SpringBoot结合SpringSecurity实现图形验证码功能

    这篇文章主要介绍了SpringBoot + SpringSecurity 实现图形验证码功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • springboot内嵌Tomcat安全漏洞修复方式

    springboot内嵌Tomcat安全漏洞修复方式

    针对CVE-2020-1938漏洞,建议升级Tomcat至安全版本以避免受影响,影响版本包括:Apache Tomcat 9.x小于9.0.31、Apache Tomcat 8.x小于8.5.51、Apache Tomcat 7.x小于7.0.100及Apache Tomcat 6.x,
    2024-10-10
  • mybatis查询结果返回至实体类的示例代码

    mybatis查询结果返回至实体类的示例代码

    这篇文章主要介绍了mybatis查询结果返回至实体类的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07

最新评论