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之事务处理机制
  • spring事务异常回滚实例解析
  • Spring+SpringMVC配置事务管理无效原因及解决办法详解
  • 详解Springboot事务管理
  • 浅谈Spring中@Transactional事务回滚及示例(附源码)
  • mybatis开启spring事务代码解析
  • 浅谈Spring的两种事务定义方式
  • 解决spring mvc 多数据源切换,不支持事务控制的问题
(0)

相关推荐

  • 解决spring mvc 多数据源切换,不支持事务控制的问题

    一个项目中需要使用两个数据库,Oracle 和Mysql,于是参考各个blog,实现此功能.写好后才发现,原来的事务失效了,我去... spring-mybatis.xml 配置 <bean id="configReader" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="location

  • 详解Springboot事务管理

    在Spring Boot事务管理中,实现自接口PlatformTransactionManager. public interface PlatformTransactionManager { org.springframework.transaction.TransactionStatus getTransaction(org.springframework.transaction.TransactionDefinition transactionDefinition) throws org.

  • Spring+SpringMVC配置事务管理无效原因及解决办法详解

    一般我们在Spring的配置文件application.xml中对Service层代码配置事务管理,可以对Service的方法进行AOP增强或事务处理如事务回滚,但是遇到一个问题,在Controller类中调用Service层方法,配置的事务管理会失效,查询相关资料发现原因.其实Spring和SpringMVC俩个容器为父子关系,Spring为父容器,而SpringMVC为子容器.也就是说application.xml中应该负责扫描除@Controller的注解如@Service,而Spring

  • 浅谈Spring中@Transactional事务回滚及示例(附源码)

    一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部门里面有很多成员,这两者分别保存在部门表和成员表里面,在删除某个部门的时候,假设我们默认删除对应的成员.但是在执行的时候可能会出现这种情况,我们先删除部门,再删除成员,但是部门删除成功了,删除成员的时候出异常了.这时候我们希望如果成员删除失败了,之前删除的部门也取消删除.这种场景就可以使用@Transactional事物回滚. 二.checked异常和unc

  • mybatis开启spring事务代码解析

    1.事务 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.最终都是调用数据库连接来完成事务的开启.提交和回滚. 2.模块 那么在对于spring事务而言,几个不可或缺的模块就是数据源.事务管理器以及事务编程 3.xml配置 <!--事务管理器--> <bean id="springTransactionManager" class="org.springframework.jdbc.datasourc

  • spring事务异常回滚实例解析

    最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug?我想多了....... 为了打印清楚日志,很多方法我都加tyrcatch,在catch中打印日志.但是这边情况来了,当这个方法异常时候日志是打印了,但是加的事务却没有回滚. 例: 类似这样的方法不会回滚(一个方法出错,另一个方法不会回滚): if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.save(capabilityQuota); } catch (Exce

  • 浅谈SpringBoot之事务处理机制

    一.Spring的事务机制 所有的数据访问技术都有事务处理机制,这些技术提供了API用来开启事务.提交事务来完成数据操作,或者在发生错误的时候回滚数据. 而Spring的事务机制是用统一的机制来处理不同数据访问技术的事务处理.Spring的事务机制提供了一个PlatformTransactionManager接口,不同的数据访问技术的事务使用不同的接口实现: 在程序中定义事务管理器的代码如下: @Bean public PlatformTransactionManager transaction

  • 浅谈Spring的两种事务定义方式

    一.声明式 这种方法不需要对原有的业务做任何修改,通过在XML文件中定义需要拦截方法的匹配即可完成配置,要求是,业务处理中的方法的命名要有规律,比如setXxx,xxxUpdate等等.详细配置如下: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="

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

    本文研究的主要是Spring事务隔离级别(solation level)介绍及例子,具体如下. 当两个事务对同一个数据库的记录进行操作时,那么,他们之间的影响是怎么样的呢?这就出现了事务隔离级别的概念.数据库的隔离性与并发控制有很大关系.数据库的隔离级别是数据库的事务特性ACID的一部分.ACID,即原子性(atomicity).一致性(consistency).隔离性(isolation)和持久性(durability).Spring的事务隔离级别有四个:READ_UNCOMMITTED.RE

  • spring事务隔离级别、传播机制以及简单配置方式

    一.spring支持的事务声明方式 1. 编程式事务 当系统需要明确的,细粒度的控制各个事务的边界,应选择编程式事务. 2. 声明式事务 当系统对于事务的控制粒度较粗时,应该选择申明式事务,通过<tx>标签和<aop>切面形式在xml中进行配置. 3. 无论你选择上述何种事务方式去实现事务控制,spring都提供基于门面设计模式的事务管理器供选择,如下是spring事务中支持的事务管理器 事务管理器实现(org.springframework.*) 使用时机 jdbc.dataso

  • Spring框架事务属性中事务隔离级别与传播行为全面讲解

    目录 一.事务隔离级别 ①介绍 ②使用方式 二.事务传播行为 ①介绍 ②测试 一.事务隔离级别 ①介绍 数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题.一个事 务与其他事务隔离的程度称为隔离级别.SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同 的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱. 隔离级别一共有四种: 读未提交:READ UNCOMMITTED 允许Transaction01读取Transaction02未提交的修改. 读已提交

  • Mysql事务隔离级别原理实例解析

    引言 大家在面试中一定碰到过 说说事务的隔离级别吧? 老实说,事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!因为他们对可重复读(Repeatable Read)和串行化(serializable)的解析实在是看的我一头雾水! 再加上很多书都说可重复读解决了幻读问题,比如<mysql技术内幕--innodb存储引擎>等,不一一列举了,因此网上关于事务隔离级别的文章大多是有问题的,所以再开一文说明! 本文所讲大部分内容,皆有

  • 通过实例分析MySQL中的四种事务隔离级别

    前言 在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别.数据库事务的隔离级别有4个,下面话不多说了,来一起看看详细的介绍吧. 数据库事务有四种隔离级别: 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据. 提交读(Read Committed):只能读取到已经提交的数据,Oracle等多数数据库默认都是该级别. 可重复读(Repeated Read):可重复读.在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级

  • Spring中的事务隔离级别和传播行为

    目录 传播行为 举个例子进行说明 1>PROPAGATION_REQUIRED 2>PROPAGATION_SUPPORTS 3>PROPAGATION_MANDATORY 4>PROPAGATION_REQUIRES_NEW 5>PROPAGATION_NOT_SUPPORTED 6>PROPAGATION_NEVER 7>PROPAGATION_NESTED 总结 Spring的事务隔离级别和事务的传播行为是面试中经常考察的问题,做个简单的总结. 传播行为 在

  • Spring 事务隔离与事务传播的详解与对比

    Spring 事务隔离与事务传播的详解与对比 Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作.今天一起学习一下Spring的事务管理.Spring的事务管理分为声明式跟编程式.声明式就是在Spring的配置文件中进行相关配置:编程式就是用注解的方式写到代码里. Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSource. Tr

  • MySQL数据库事务隔离级别介绍(Transaction Isolation Level)

    数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 复制代码 代码如下: #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. [mysqld] transaction-isolation = REPEATABLE-READ 这里全局默认是REPEATABLE-READ,其实MySQL本来默认也是这个级别

  • mysql+Spring数据库隔离级别与性能分析

    这里以mysql为例,先明确以下几个问题: 一.一般项目如果不自己配置事务的话,一般默认的是autocommit,即执行完一个操作后自动commit,提交事务. (注:事务是绑定在数据库操作上的,也就是当程序执行(statement.excute等操作)转而到数据库层面上的时候,事务才开始发生)当然spring可以将几个数据库操作动作绑在一个事务中,这样就需要介绍下spring事务配置方法,下面介绍的是常用方法,其他方法网上有很多.spring提供了很多事务配置的策略,很方便,简要介绍一下: 复

  • MySQL中Innodb的事务隔离级别和锁的关系的讲解教程

    前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. 一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会

随机推荐