时间:2021-05-20
本文研究的主要是Spring事务隔离级别(solation level)介绍及例子,具体如下。
当两个事务对同一个数据库的记录进行操作时,那么,他们之间的影响是怎么样的呢?这就出现了事务隔离级别的概念。数据库的隔离性与并发控制有很大关系。数据库的隔离级别是数据库的事务特性ACID的一部分。ACID,即原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。Spring的事务隔离级别有四个:READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。还有一个,是数据库默认的隔离级别DEFAULT,MySQL默认是REPEATABLE_READ。
下面来具体看看。
顾名思义,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隔离级别表明,一个事务只能读取到已经提交的记录,不能读取到未提交的记录。换句话说,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意思是,一个事务可以多次从数据库读取某条记录,而且多次读取的那条记录都是一致的,相同的。这个隔离级别可以避免dirty read和non-repeatable read的问题,但可能发生phantom read的问题。如下图。
事务A两次从数据库读取一系列记录,期间,事务B插入了某条记录并提交。事务A第二次读取时,会读取到事务B刚刚插入的那条记录。在事务期间,事务A两次读取的一系列记录不一致,这个问题称为phantom read。
SERIALIZABLE是Spring最强的隔离级别。事务执行时,会在所有级别上加锁,比如read和write时都会加锁,仿佛事务是以串行的方式进行的,而不是一起发生的。这会防止dirty read、non-repeatable read和phantom read的出现,但是,会带来性能的下降。
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事务隔离级别简介及实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
MySQL四种事务隔离级别详解及对比按照SQL:1992事务隔离级别,InnoDB默认是可重复读的(REPEATABLEREAD)。MySQL/InnoDB提供
入口(了解一些基本概念)Spring事务属性(事务的属性有哪些?)我们都知道事务有开始,保存点,提交,回滚,隔离级别等属性。那么Spring对于事务属性
1、Spring的事务管理主要包括3个接口TransactionDefinition:封装事务的隔离级别,超时时间,是否为只读事务和事务的传播规则等事务属性,可
前言在前面的内容,基本已经学习了事务的基本概念以及事务隔离级别等,接下来的几个小节,将学习怎么使用Spring进行事务管理,在Spring中,对事务进行管理有多
隔离级别:隔离性其实比想象的要复杂。在SQL标准中定义了四种隔离级别,每一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可