个传播行为,4个隔离级别,
Spring事务的传播行为和隔离级别
[
transaction
behavior and
isolated level
]
事务的传播行为和隔离级别
[
transaction
behavior and
isolated level
]
Spring中事务的定义:
一、Propagation
:
key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:
PROPAGATION_REQUIRED
-
-
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS
-
-
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
-
-
支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
-
-
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED
-
-
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
-
-
以非事务方式执行,如果当前存在事务,则抛出异常。
很多人看到事务的传播行为属性都不甚了解,我昨晚看了j2ee without
ejb的时候,看到这里也不了解,甚至重新翻起数据库系统的教材书,但是也没有找到对这个的分析。今天搜索,找到一篇极好的分析文章,虽然这篇文章是重点分析PROPAGATION_REQUIRED
和 PROPAGATION_REQUIRED_NESTED的
解惑 spring 嵌套事务 /** * @date 2006-11-24 * @note 转载自http://www.javaeye.com/topic/35907?page=1 */ * * * * * * * * TransactionDefinition 接口定义* * * * * * * * * * * * * * * * * * * /** * Support a current transaction, create a new one if none exists. * Analogous to EJB transaction attribute of the same name. * This is typically the default setting of a transaction definition. */ int PROPAGATION_REQUIRED = 0; /** * Support a current transaction, execute non-transactionally if none exists. * Analogous to EJB transaction attribute of the same name. * Note: For transaction managers with transaction synchronization, * PROPAGATION_SUPPORTS is slightly different from no transaction at all, * as it defines a transaction scopp that synchronization will apply for. * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) * will be shared for the entire specified scope. Note that this depends on * the actual synchronization configuration of the transaction manager. * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization */ int PROPAGATION_SUPPORTS = 1; /** * Support a current transaction, throw an exception if none exists. * Analogous to EJB transaction attribute of the same name. */ int PROPAGATION_MANDATORY = 2; /** * Create a new transaction, suspend the current transaction if one exists. * Analogous to EJB transaction attribute of the same name. * Note: Actual transaction suspension will not work on out-of-the-box * on all transaction managers. This in particular applies to JtaTransactionManager, * which requires the javax.transaction.TransactionManager to be * made available it to it (which is server-specific in standard J2EE). * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager */ int PROPAGATION_REQUIRES_NEW = 3; /** * Execute non-transactionally, suspend the current transaction if one exists. * Analogous to EJB transaction attribute of the same name. * Note: Actual transaction suspension will not work on out-of-the-box * on all transaction managers. This in particular applies to JtaTransactionManager, * which requires the javax.transaction.TransactionManager to be * made available it to it (which is server-specific in standard J2EE). * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager */ int PROPAGATION_NOT_SUPPORTED = 4; /** * Execute non-transactionally, throw an exception if a transaction exists. * Analogous to EJB transaction attribute of the same name. */ int PROPAGATION_NEVER = 5; /** * Execute within a nested transaction if a current transaction exists, * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB. * Note: Actual creation of a nested transaction will only work on specific * transaction managers. Out of the box, this only applies to the JDBC * DataSourceTransactionManager when working on a JDBC 3.0 driver. * Some JTA providers might support nested transactions as well. * @see org.springframework.jdbc.datasource.DataSourceTransactionManager */ int PROPAGATION_NESTED = 6;
在这篇文章里,他用两个嵌套的例子辅助分析,我这里直接引用了。
ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
@Transactional(propagation=Propagation.REQUIRED)
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
@Transactional(propagation=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
*/
@Transactional(propagation=Propagation.REQUIRED)
void methodA() {
try {
//savepoint
@Transactional(propagation=Propagation.NESTED)
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}
}
也就是说ServiceB.
methodB失败回滚,那么ServiceA.
methodA也会回滚到savepoint点上,ServiceA.
methodA可以选择另外一个分支,比如
ServiceC.
methodC,继续执行,来尝试完成自己的事务。
但是这个事务并没有在EJB标准中定义。
二、Isolation Level
(
事务隔离等级)
:
1、Serializable:最严格的级别,事务串行执行,资源消耗最大;
2、REPEATABLE
READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
3、READ COMMITTED:
大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
4、Read Uncommitted:保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1: Dirty
reads
-
-
读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。
2: non-
repeatable reads
-
-
数据不可重复读。比如事务A中两处读取数据-
total-
的值。在第一读的时候,total是100,然后事务B就把total的数据改成200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。
3: phantom reads
-
-
幻象读数据,这个和non-
repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-
repeatable
reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom
reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.
id
where
account.
name
=
"ppgogo*"
,
第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"
改成"ppgogo1"
,结果取出来了7个数据。 Dirty
reads non-
repeatable reads phantom reads
Serializable
不会 不会 不会
REPEATABLE READ
不会 不会 会
READ
COMMITTED 不会 会 会
Read
Uncommitted 会 会 会
三、readOnly
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。
这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/
Relational映射工具(如:Hibernate或TopLink)时避免dirty
checking(试图“刷新”)。
四、Timeout
在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。
转载自:http://blog.chinaunix.net/u1/55983/showart_2091761.html
附:@interface Transactional
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.transaction.TransactionDefinition;
/**
* Describes transaction attributes on a method or class.
*
* <p>This annotation type is generally directly comparable to Spring's
* {@link org.springframework.transaction.interceptor.RuleBasedTransactionAttribute}
* class, and in fact {@link AnnotationTransactionAttributeSource} will directly
* convert the data to the latter class, so that Spring's transaction support code
* does not have to know about annotations. If no rules are relevant to the exception,
* it will be treated like
* {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute}
* (rolling back on runtime exceptions).
*
* <p>For specific information about the semantics of this annotation's attributes,
* consider the {@link org.springframework.transaction.TransactionDefinition} and
* {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs.
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @since 1.2
* @see org.springframework.transaction.interceptor.TransactionAttribute
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute
* @see org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
* A qualifier value for the specified transaction.
* <p>May be used to determine the target transaction manager,
* matching the qualifier value (or the bean name) of a specific
* {@link org.springframework.transaction.PlatformTransactionManager}
* bean definition.
*/
String value() default "";
/**
* The transaction propagation type.
* Defaults to {@link Propagation#REQUIRED}.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
*/
Propagation propagation() default Propagation.REQUIRED;
/**
* The transaction isolation level.
* Defaults to {@link Isolation#DEFAULT}.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel()
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* The timeout for this transaction.
* Defaults to the default timeout of the underlying transaction system.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
*/
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/**
* <code>true</code> if the transaction is read-only.
* Defaults to <code>false</code>.
* <p>This just serves as a hint for the actual transaction subsystem;
* it will <i>not necessarily</i> cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will
* <i>not</i> throw an exception when asked for a read-only transaction.
* @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
*/
boolean readOnly() default false;
/**
* Defines zero (0) or more exception {@link Class classes}, which must be a
* subclass of {@link Throwable}, indicating which exception types must cause
* a transaction rollback.
* <p>This is the preferred way to construct a rollback rule, matching the
* exception class and subclasses.
* <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}
*/
Class<? extends Throwable>[] rollbackFor() default {};
/**
* Defines zero (0) or more exception names (for exceptions which must be a
* subclass of {@link Throwable}), indicating which exception types must cause
* a transaction rollback.
* <p>This can be a substring, with no wildcard support at present.
* A value of "ServletException" would match
* {@link javax.servlet.ServletException} and subclasses, for example.
* <p><b>NB: </b>Consider carefully how specific the pattern is, and whether
* to include package information (which isn't mandatory). For example,
* "Exception" will match nearly anything, and will probably hide other rules.
* "java.lang.Exception" would be correct if "Exception" was meant to define
* a rule for all checked exceptions. With more unusual {@link Exception}
* names such as "BaseBusinessException" there is no need to use a FQN.
* <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)}
*/
String[] rollbackForClassName() default {};
/**
* Defines zero (0) or more exception {@link Class Classes}, which must be a
* subclass of {@link Throwable}, indicating which exception types must <b>not</b>
* cause a transaction rollback.
* <p>This is the preferred way to construct a rollback rule, matching the
* exception class and subclasses.
* <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}
*/
Class<? extends Throwable>[] noRollbackFor() default {};
/**
* Defines zero (0) or more exception names (for exceptions which must be a
* subclass of {@link Throwable}) indicating which exception types must <b>not</b>
* cause a transaction rollback.
* <p>See the description of {@link #rollbackForClassName()} for more info on how
* the specified names are treated.
* <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)}
*/
String[] noRollbackForClassName() default {};
}
enum Propagation:
/* * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.transaction.annotation; import org.springframework.transaction.TransactionDefinition; /** * Enumeration that represents transaction propagation behaviors for use * with the {@link Transactional} annotation, corresponding to the * {@link TransactionDefinition} interface. * * @author Colin Sampaleanu * @author Juergen Hoeller * @since 1.2 */ public enum Propagation { /** * Support a current transaction, create a new one if none exists. * Analogous to EJB transaction attribute of the same name. * <p>This is the default setting of a transaction annotation. */ REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), /** * Support a current transaction, execute non-transactionally if none exists. * Analogous to EJB transaction attribute of the same name. * <p>Note: For transaction managers with transaction synchronization, * PROPAGATION_SUPPORTS is slightly different from no transaction at all, * as it defines a transaction scope that synchronization will apply for. * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) * will be shared for the entire specified scope. Note that this depends on * the actual synchronization configuration of the transaction manager. * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization */ SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), /** * Support a current transaction, throw an exception if none exists. * Analogous to EJB transaction attribute of the same name. */ MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), /** * Create a new transaction, suspend the current transaction if one exists. * Analogous to EJB transaction attribute of the same name. * <p>Note: Actual transaction suspension will not work on out-of-the-box * on all transaction managers. This in particular applies to JtaTransactionManager, * which requires the <code>javax.transaction.TransactionManager</code> to be * made available it to it (which is server-specific in standard J2EE). * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager */ REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), /** * Execute non-transactionally, suspend the current transaction if one exists. * Analogous to EJB transaction attribute of the same name. * <p>Note: Actual transaction suspension will not work on out-of-the-box * on all transaction managers. This in particular applies to JtaTransactionManager, * which requires the <code>javax.transaction.TransactionManager</code> to be * made available it to it (which is server-specific in standard J2EE). * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager */ NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), /** * Execute non-transactionally, throw an exception if a transaction exists. * Analogous to EJB transaction attribute of the same name. */ NEVER(TransactionDefinition.PROPAGATION_NEVER), /** * Execute within a nested transaction if a current transaction exists, * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB. * <p>Note: Actual creation of a nested transaction will only work on specific * transaction managers. Out of the box, this only applies to the JDBC * DataSourceTransactionManager when working on a JDBC 3.0 driver. * Some JTA providers might support nested transactions as well. * @see org.springframework.jdbc.datasource.DataSourceTransactionManager */ NESTED(TransactionDefinition.PROPAGATION_NESTED); private final int value; Propagation(int value) { this.value = value; } public int value() { return this.value; } }
相关推荐
spring事务的传播特性和事务隔离级别
事务传播特性&事务隔离级别 详细的事务传播特性&事务隔离级别
spring 事务传播与隔离级别DEMO 脏读、重复读、幻影读 spring 事务传播与隔离级别DEMO 脏读、重复读、幻影读
Spring事务的传播特性和隔离级别 事务的几种传播特性详细介绍
事务的属性:1.Propagation:用来设置事务的传播行为事务的传播行为:一个方法运行在了一个开启了事务的方法中时,当前方法是使用原来的事务还是开启了一个新
主要介绍了Spring事务传播属性和隔离级别详细介绍,同时涉及传播行为介绍,超时设置等相关内容,需要的朋友可以参考下。
Java面试题54.Spring事务的传播特性和隔离级别.mp4
系统理解spring事务传播属性,和隔离级别
Spring控制Hibernate中的事务传播特性与隔离级别操作,通过利用spring和Hibernate的两个HibernateTemplate 和 jdbcTemplate类,实现数据的交互。
Spring 管理事务(传播特性、隔离级别、readonly).rar
02.Spring支持的常用数据库事务传播属性和事务隔离级别
java面试宝典
【Spring五个事务隔离级别和七个事务传播行为】 数据库事务和Spring事务是一般面试都会被提到,很多朋友写惯了代码,很少花时间去整理归纳这些东西,结果本来会的东西,居然吞吞吐吐答不上来。 下面是我收集到一些...
上面我们只是简单的使用事务,这里将讨论Spring事务机制中最重要的两个配置项,即隔离级别与传播行为。毫无疑问本节内容是本章的核心内容,也是互联网企业最关注的内容之一,因此他十分重要,值得花费大的篇幅去讨论...
此ppt中前半部分通过spring事务的60道题的测试,摸底对事务的掌握情况,后半部分,对spring中的事务属性(传播行为、隔离级别、回滚规则、事务超时、是否只读)进行说明
上文理解到对spring事物,事物的隔离机制,这片具体说下事物的传播机制和隔离机制
Spring 事务隔离与事务传播的详解与对比 Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作。今天一起学习一下Spring的事务管理。Spring的事务管理分为声明式跟编程式。声明式就是在Spring的配置文件中...
可以在spring中对整个项目的事务进行控制
此外,Spring事务管理器支持多种类型的事务策略,包括不同的传播行为和隔离级别,允许开发者根据具体业务场景选择最合适的事务管理策略。深入理解Spring声明式事务的工作原理,不仅能帮助开发者更高效地使用Spring...
3.并发事务带来的问题和解决方案(包含四种隔离级别和会产生的锁) 4.逐个分析脏读,不可重复读和幻读出现的场景和解决方案 5.事务的底层原理(附带流程图) 6.事务的7种传播性、使用场景和实际场景 7.spring事务15...