脏读:一个事物正在访问数据,并且对数据进行了修改,但是还没有提交到数据库。这个时候,另一个事务读取了这部分没有提交的数据
不可重复读:是指在一个事物内多次读取同一数据。在这个事务还没有结束时,另一个事务对该数据进行了修改。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读。
不可重复读的重点是修改 :
同样的条件,你读取过的数据,再次读取出来发现值不一样了。
幻读:是指当事务不是独立执行时发生的一种现象。例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
幻读的重点在于新增或者删除
同样的条件,第 1 次和第 2 次读出来的记录数不一样。
为了解决上面的三个问题,出现了以下几种隔离级别:
ISOLATION_READ_UNCOMMITTED
这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
ISOLATION_READ_COMMITTED
保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。(锁定正在读取的行)
ISOLATION_REPEATABLE_READ
这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。(锁定所读取的所有行)
ISOLATION_SERIALIZABLE
这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。(锁表)
传播行为
REQUIRED————支持当前事务,如果当前没有事务,则新建一个事务。这是最常见的选择。
SUPPORTS————支持当前事务,如果当前没有事务,就以非事务方式运行。
MANDETORY————支持当前事务,如果当前没有事务,则抛出异常。
REQUIRES_NEW————总是新建一个事务。如果当前存在事务,则将当前的事务挂起。
NOT_SUPPORTED————在非事务下运行,如果当前存在事务,则将当前的事务挂起。
NEVER————在非事务下运行,如果当前存在事务,则抛出异常。
NESTED————如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动事务,则按REQUIRED属性执行。
下面举例分析一下这6中传播行为:
ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodB() {
}
} *************************************************
1:PROPAGATION_REQUIRED
假入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务。
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。 这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚。
2:PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行。这就跟平常用的普通非事务的代码只有一点点区别了。不理这个,因为我也没有觉得有什么区别。
3:PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。
4:PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。
5:PROPAGATION_NOT_SUPPORTED
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
6:PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER , 那么ServiceB.methodB就要抛出异常了。
7:PROPAGATION_NESTED
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。 而Nested事务的好处是他有一个savepoint。
*****************************************
ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}
}
********************************************
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。
注意点:
必须要满足两个条件才能createSavepoint :
1. java.sql.Savepoint 必须存在, 即 jdk 版本要 1.4+
2. Connection.getMetaData().supportsSavepoints() 必须为 true, 即 jdbc drive 必须支持 JDBC 3.0
确保以上条件都满足后, 你就可以尝试使用 PROPAGATION_NESTED 了.
参考博客:http://dapeng.iteye.com/blog/155178
相关推荐
Spring通过`@Transactional`注解可以方便地设置事务传播行为和隔离级别,例如: ```java @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public void ...
4. **声明式事务管理**:Spring允许在配置文件中声明事务边界,这样可以在多个方法之间定义事务传播行为和隔离级别,而无需在代码中显式处理。 例如,以下是如何使用HibernateTemplate删除Userinfo对象: ```java ...
### Spring事务的传播特性和事务隔离级别 #### 一、Spring事务的传播特性(Propagation) 在Spring框架中,事务管理不仅提供了ACID属性的支持,还引入了事务的传播特性,这些特性决定了当一个方法调用另一个方法时,...
事务传播特性&事务隔离级别 事务传播特性是指在 Java 中,事务的传播行为,即在多个...事务传播特性和事务隔离级别是 Java 中事务管理的两个重要方面,需要深入了解和正确使用,以确保事务的正确执行和数据的一致性。
Spring 框架提供了一套完善的事务管理机制,其中包含了多种事务传播属性和事务隔离级别。这些特性使得在处理数据库操作时,能够更好地控制事务的边界和行为,从而确保数据的一致性和完整性。 首先,我们来看一下...
### Spring 事务传播特性和事务隔离级别详解 #### 一、Spring 事务传播特性 在进行多层服务架构设计时,事务的管理尤其重要。为了确保数据的一致性,Spring 提供了一种灵活的方式来控制事务的传播行为。下面详细...
事务传播行为定义了当方法被另一个带有事务属性的方法调用时,该方法如何处理事务。Spring 提供了多种不同的传播行为选项,这些选项可以帮助开发者更好地控制事务的创建与参与。 #### 1. `@Transactional...
### Spring 事务隔离和传播机制详解 #### 一、Spring 事务传播机制 Spring 的事务管理功能非常强大,其中一个重要特性...在实际开发中,选择合适的事务传播行为和隔离级别对于保证数据一致性、避免并发问题至关重要。
### Spring事务的传播特性和隔离级别 #### 一、事务的基本概念 在计算机科学中,事务(transaction)是指一系列操作的集合,这些操作要么全部成功完成,要么全部失败回滚,确保数据的一致性和完整性。事务具备四个...
### Spring事务的七大传播行为 ...总结来说,选择合适的事务传播行为和隔离级别对于确保应用程序的数据一致性至关重要。开发者需要根据业务需求权衡性能和数据一致性之间的关系,以选择最合适的设置。
"spring注解式事务" Spring框架提供了基于注解的方式来管理事务,使用@Transactional注解来标记...Spring框架提供了灵活的方式来管理事务,开发者可以根据实际情况选择合适的事务传播行为和隔离级别来满足业务需求。
### 深入理解Spring的事务管理机制 #### 一、事务的基本原理 Spring框架的事务管理机制是在Java开发环境中非常...开发者可以根据具体的业务需求来选择合适的事务传播行为和隔离级别,从而确保应用的一致性和高效性。
- 根据需求选择合适的事务传播行为和隔离级别。 - 在处理异常时,合理设置rollbackFor和noRollbackFor,确保事务的正确回滚或继续执行。 通过这些知识点,我们可以更好地理解和运用Spring框架的注解式声明性事务...
综上所述,理解并熟练掌握Spring的事务管理机制,包括传播特性、隔离级别和readonly属性,对于开发高效、稳定的业务系统至关重要。正确配置和使用这些特性,能有效防止并发控制中的异常情况,保障数据的完整性和一致...
Spring的事务管理还提供了强大的事务传播行为和隔离级别配置,开发者可以根据业务需求来设置事务如何在多个方法调用之间传播,以及事务之间的隔离程度,保证数据的一致性和隔离性。 在实际应用中,Spring事务管理的...
通过灵活运用声明式和编程式事务,以及正确设置事务传播行为和隔离级别,我们可以构建出稳定、健壮的业务系统。在实际项目中,还需要根据业务需求和性能考虑,合理选择事务策略,以实现最佳效果。
对于事务管理的核心逻辑,如事务传播行为和隔离级别,可以在XML配置中统一定义,而对于具体业务方法的事务控制,可以使用注解进行精细化管理。 总结来说,Spring的声明式事务管理是其强大的企业级功能之一,它通过...
在Java应用开发中,特别是使用Spring框架时,开发者可以通过配置不同的事务传播行为来控制事务如何在方法调用之间传播。这些传播行为对于理解并正确实现业务逻辑至关重要。 #### 二、事务传播特性的种类 根据给定...
在这里,`transactionAttributes`属性定义了不同方法名前缀下的事务传播行为和隔离级别。 2. **基于注解的AOP代理配置** Spring也支持使用@Transactional注解来声明事务边界。这种方式下,需要启用组件扫描并配置...