您的位置:首页 > 编程语言 > Java开发

Spring 事务的隔离级别和传播行为的理解

2017-04-18 10:40 330 查看

一、Spring 事务的隔离级别

在了解Spring事务隔离级别前,先弄清楚以下概念:

脏读:脏读发生在一个事务读取了被另一个事务改写但还未提交的数据时。如果这些改变在稍后被回滚,那么之前的事务读取的到数据就是无效的。

不可重复读:不可重复读发生在一个事务执行相同的查询两次或两次以上,但每一次的查询结果不同时。这通常是由于另一个并发的事务在两次查询之间更新了数据。

幻读:幻读是一个事务读取几行记录后,另一个事务插入了一些记录,幻读就发生了。在后来的查询中第一个事务就会发现有一些原来没有的额外的记录。

(1)ISOLATION_DEFAULT

使用数据的隔离级别

(2)ISOLATION_READ_UNCOMMITTED

允许读取改变了的还未提交的数据,可能导致脏读、不可重复读和幻读

(3)ISOLATION_READ_COMMITTED

允许并发事务提交之后读取,可以避免脏读,可能导致重复读和幻读

(4)ISOLATION_REPEATABLE_READ

对相同字段的多次读取结果一致,可导致幻读

(5)ISOLATION_SERIALIZABLE

完全服从ACID的原则,确保不发生脏读、不可重复读和幻读

二、Spring 事务的传播行为

在了解Spring事务传播行为前,先看一下代码:

@Service
public class ConsumerServiceImpl implements ConsumerService {

@Autowired
private ProviderService providerService;

@Transactional(propagation = ConsumerPropagation)
public void consume() {
provideBeforeCode;
providerService.provide();
provideAfterCode;
}
}

@Service
public class ProviderServiceImpl implements ProviderService {

@Transactional(propagation = ProviderPropagation)
public void provide() {
provideCode;
}
}


(1) PROPAGATION_REQUIRED

是Spring默认的传播行为。 支持当前事务。如果不存在,则新建一个;如果存在,则加入当前事务中。> 所以,整个过程,Spring创建了一个事务,这个事务包含了所有内容。如以上代码,ConsumerPropagation为Propagation.REQUIRED,ConsumerPropagation为Propagation.REQUIRED,这样的话provideBeforeCode;provideAfterCode;provideCode;会在同一个事务中,无论哪一块代码发生运行时异常该事务都会回滚(Spring 默认发生运行时异常会回滚事务),即使provideCode发生运行时异常向外抛出,且providerService.provide();被try catch,异常不抛出,也会回滚,因为在provideCode发生运行时异常向外抛出时,Spring会将该事务标记为robackOnly为true,即使异常没有在consume抛出,Spring在提交事务时,会报Transaction marked as rollbackOnly错误。

(2) PROPAGATION_REQUIRES_NEW

如果存在一个事务,则挂起当前事务,创建一个新的事务;如果不存在,则直接创建一个新的事务。

1> ConsumerPropagation为Propagation.REQUIRED,ConsumerPropagation为Propagation.REQUIRES_NEW;那么provideBeforeCode;provideAfterCode;在一个事务中,provideCode;在另一个事务中;如果provideCode;发生运行时异常且向外抛出,那么provideCode;所处的事务将会回滚。如果providerService.provide();没有被try catch,那么provideBeforeCode;provideAfterCode;所处的事务也会回滚,如果providerService.provide();被try catch且没有向外抛出,那么provideBeforeCode;provideAfterCode;所处的事务不会回滚。

2>ConsumerPropagation为Propagation.REQUIRED,ConsumerPropagation为Propagation.REQUIRES_NEW;如果provideAfterCode;发生运行时异常且向外抛出,那么provideBeforeCode;provideAfterCode;会被回滚,而provideCode;不会回滚;

(3) PROPAGATION_SUPPORTS

支持当前事务。如果不存在,则以非事务形式执行;如果存在,则加入当前事务中。

(4) PROPAGATION_NOT_SUPPORTED

不支持当前事务。如果不存在,则以非事务形式执行;如果存在,则挂起当前事务,以非事务形式执行,执行完毕后再恢复原事务继续执行。

(5) PROPAGATION_MANDATORY

支持当前事务。如果不存在,则抛出一个异常;如果存在,则加入当前事务中。

(6) PROPAGATION_NEVER

不支持当前事务。如果不存在,则以非事务形式执行;如果存在,则抛出一个异常。

(7) PROPAGATION_NESTED

如果当前存在一个事务,则嵌入一个事务并执行;如果不存在一个事务,则新建一个事务并执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: