基于 Spring事务分析总结 - JavaGuide 的总结
[TOC]
Spring 事务分析总结
事务的概念
什么是事务:
事务是由一组SQL语句组成的逻辑执行单元,这些语句要么全部执行,要么全部不执行。
事务的四大特性(ACID):
* 原子性
* 一致性
* 隔离性
* 持久性
隔离级别:
* 读未提交(脏读、不可重复读、幻读)
* 读已提交(不可重复读、幻读)
* 可重复读(幻读)
* 串行化
MySQL 如何保证原子性:
回滚日志(undo log)
MySQL 如何保证持久性:
重做日志(redo log)
Spring 对事务的支持
Spring 支持的两种事务管理的方式
Spring 支持两种事务管理的方式:
* 声明式事务
* 编程式事务
编程式事务
通过 TransactionManager
或 TransactionTemplate
手动管理事务:
@Autowired
private PlatformTransactionManager transactionManager;
public void testTransactionManager(){
TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
// 业务代码
transactionManager.commit(transaction);
}catch (Exception e){
// 回滚
transactionManager.rollback(transaction);
}
}
@Autowired
TransactionTemplate transactionTemplate;
public void testTransactionTemplate(){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
// 业务代码
}catch (Exception e){
// 回滚
status.setRollbackOnly();
}
}
});
}
声明式事务
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public void testTransaction(){
// 业务代码
}
事务管理接口介绍
在Spring 框架中,与事务管理相关的三个重要接口:
-
PlatformTransactionManager
:为各平台的事务管理提供了抽象的接口 -
TransactionDefinition
:事务定义(隔离级别、传播行为、超时、只读、回滚规则) -
TransactionStatus
:事务状态(是否回滚、是否完成)
Spring 对事务管理的设计采用了 适配器模式:
1. Spring 定义了事务管理器的抽象接口 PlatformTransactionManager
2. Spring 为各平台提供了事务管理器的实现:DataSourceTransactionManager, HibernateTransactionManager, JpaTransactionManager
3. 各平台提供了事务管理的具体实现
Spring 通过事务管理器使各平台的事务管理实现适配 PlatformTransactionManager,从对事务管理提供了一致的编程模型
PlatformTransactionManager 接口
PlatformTransactionManager
接口:
package org.springframework.transaction;
import org.springframework.lang.Nullable;
/**
* This is the central interface in Spring's imperative transaction infrastructure.
* Applications can use this directly, but it is not primarily meant as an API:
* Typically, applications will work with either TransactionTemplate or
* declarative transaction demarcation through AOP.
*
* For implementors, it is recommended to derive from the provided
* {@link org.springframework.transaction.support.AbstractPlatformTransactionManager}
* class, which pre-implements the defined propagation behavior and takes care
* of transaction synchronization handling. Subclasses have to implement
* template methods for specific states of the underlying transaction,
* for example: begin, suspend, resume, commit.
*
*
The default implementations of this strategy interface are
* {@link org.springframework.transaction.jta.JtaTransactionManager} and
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager},
* which can serve as an implementation guide for other transaction strategies.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 16.05.2003
* @see org.springframework.transaction.support.TransactionTemplate
* @see org.springframework.transaction.interceptor.TransactionInterceptor
* @see org.springframework.transaction.ReactiveTransactionManager
*/
public interface PlatformTransactionManager extends TransactionManager {
/**
* Return a currently active transaction or create a new one, according to
* the specified propagation behavior.
*
Note that parameters like isolation level or timeout will only be applied
* to new transactions, and thus be ignored when participating in active ones.
*
Furthermore, not all transaction definition settings will be supported
* by every transaction manager: A proper transaction manager implementation
* should throw an exception when unsupported settings are encountered.
*
An exception to the above rule is the read-only flag, which should be
* ignored if no explicit read-only mode is supported. Essentially, the
* read-only flag is just a hint for potential optimization.
* @param definition the TransactionDefinition instance (can be {@code null} for defaults),
* describing propagation behavior, isolation level, timeout etc.
* @return transaction status object representing the new or current transaction
* @throws TransactionException in case of lookup, creation, or system errors
* @throws IllegalTransactionStateException if the given transaction definition
* cannot be executed (for example, if a currently active transaction is in
* conflict with the specified propagation behavior)
* @see TransactionDefinition#getPropagationBehavior
* @see TransactionDefinition#getIsolationLevel
* @see TransactionDefinition#getTimeout
* @see TransactionDefinition#isReadOnly
*/
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
/**
* Commit the given transaction, with regard to its status. If the transaction
* has been marked rollback-only programmatically, perform a rollback.
*
If the transaction wasn't a new one, omit the commit for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after committing the new one.
*
Note that when the commit call completes, no matter if normally or
* throwing an exception, the transaction must be fully completed and
* cleaned up. No rollback call should be expected in such a case.
*
If this method throws an exception other than a TransactionException,
* then some before-commit error caused the commit attempt to fail. For
* example, an O/R Mapping tool might have tried to flush changes to the
* database right before commit, with the resulting DataAccessException
* causing the transaction to fail. The original exception will be
* propagated to the caller of this commit method in such a case.
* @param status object returned by the {@code getTransaction} method
* @throws UnexpectedRollbackException in case of an unexpected rollback
* that the transaction coordinator initiated
* @throws HeuristicCompletionException in case of a transaction failure
* caused by a heuristic decision on the side of the transaction coordinator
* @throws TransactionSystemException in case of commit or system errors
* (typically caused by fundamental resource failures)
* @throws IllegalTransactionStateException if the given transaction
* is already completed (that is, committed or rolled back)
* @see TransactionStatus#setRollbackOnly
*/
void commit(TransactionStatus status) throws TransactionException;
/**
* Perform a rollback of the given transaction.
*
If the transaction wasn't a new one, just set it rollback-only for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after rolling back the new one.
*
Do not call rollback on a transaction if commit threw an exception.
* The transaction will already have been completed and cleaned up when commit
* returns, even in case of a commit exception. Consequently, a rollback call
* after commit failure will lead to an IllegalTransactionStateException.
* @param status object returned by the {@code getTransaction} method
* @throws TransactionSystemException in case of rollback or system errors
* (typically caused by fundamental resource failures)
* @throws IllegalTransactionStateException if the given transaction
* is already completed (that is, committed or rolled back)
*/
void rollback(TransactionStatus status) throws TransactionException;
}
TransactionDefinition 接口
TransactionDefinition 定义了事务属性:隔离级别、传播行为、只读、超时、回滚规则
package org.springframework.transaction;
import org.springframework.lang.Nullable;
/**
* Interface that defines Spring-compliant transaction properties.
*/
public interface TransactionDefinition {
/**
* Support a current transaction; create a new one if none exists.
*/
int PROPAGATION_REQUIRED = 0;
/**
* Support a current transaction; execute non-transactionally if none exists.
*/
int PROPAGATION_SUPPORTS = 1;
/**
* Support a current transaction; throw an exception if no current transaction exists.
*/
int PROPAGATION_MANDATORY = 2;
/**
* Create a new transaction, suspending the current transaction if one exists.
*/
int PROPAGATION_REQUIRES_NEW = 3;
/**
* Do not support a current transaction; rather always execute non-transactionally.
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/**
* Do not support a current transaction; throw an exception if a current transaction
* exists.
*/
int PROPAGATION_NEVER = 5;
/**
* Execute within a nested transaction if a current transaction exists,
*/
int PROPAGATION_NESTED = 6;
/**
* Use the default isolation level of the underlying datastore.
* All other levels correspond to the JDBC isolation levels.
* @see java.sql.Connection
*/
int ISOLATION_DEFAULT = -1;
/**
* Indicates that dirty reads, non-repeatable reads and phantom reads
* can occur.
* This level allows a row changed by one transaction to be read by another
* transaction before any changes in that row have been committed (a "dirty read").
* If any of the changes are rolled back, the second transaction will have
* retrieved an invalid row.
* @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
*/
int ISOLATION_READ_UNCOMMITTED = 1; // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
/**
* Indicates that dirty reads are prevented; non-repeatable reads and
* phantom reads can occur.
*
This level only prohibits a transaction from reading a row
* with uncommitted changes in it.
* @see java.sql.Connection#TRANSACTION_READ_COMMITTED
*/
int ISOLATION_READ_COMMITTED = 2; // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;
/**
* Indicates that dirty reads and non-repeatable reads are prevented;
* phantom reads can occur.
*
This level prohibits a transaction from reading a row with uncommitted changes
* in it, and it also prohibits the situation where one transaction reads a row,
* a second transaction alters the row, and the first transaction re-reads the row,
* getting different values the second time (a "non-repeatable read").
* @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
*/
int ISOLATION_REPEATABLE_READ = 4; // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;
/**
* Indicates that dirty reads, non-repeatable reads and phantom reads
* are prevented.
*
This level includes the prohibitions in {@link #ISOLATION_REPEATABLE_READ}
* and further prohibits the situation where one transaction reads all rows that
* satisfy a {@code WHERE} condition, a second transaction inserts a row
* that satisfies that {@code WHERE} condition, and the first transaction
* re-reads for the same condition, retrieving the additional "phantom" row
* in the second read.
* @see java.sql.Connection#TRANSACTION_SERIALIZABLE
*/
int ISOLATION_SERIALIZABLE = 8; // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;
/**
* Use the default timeout of the underlying transaction system,
* or none if timeouts are not supported.
*/
int TIMEOUT_DEFAULT = -1;
/**
* Return the propagation behavior.
*
Must return one of the {@code PROPAGATION_XXX} constants
* defined on {@link TransactionDefinition this interface}.
*
The default is {@link #PROPAGATION_REQUIRED}.
* @return the propagation behavior
* @see #PROPAGATION_REQUIRED
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
*/
default int getPropagationBehavior() {
return PROPAGATION_REQUIRED;
}
/**
* Return the isolation level.
*
Must return one of the {@code ISOLATION_XXX} constants defined on
* {@link TransactionDefinition this interface}. Those constants are designed
* to match the values of the same constants on {@link java.sql.Connection}.
*
Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions. Consider switching the "validateExistingTransactions" flag to
* "true" on your transaction manager if you'd like isolation level declarations
* to get rejected when participating in an existing transaction with a different
* isolation level.
*
The default is {@link #ISOLATION_DEFAULT}. Note that a transaction manager
* that does not support custom isolation levels will throw an exception when
* given any other level than {@link #ISOLATION_DEFAULT}.
* @return the isolation level
* @see #ISOLATION_DEFAULT
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
*/
default int getIsolationLevel() {
return ISOLATION_DEFAULT;
}
/**
* Return the transaction timeout.
*
Must return a number of seconds, or {@link #TIMEOUT_DEFAULT}.
*
Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions.
*
Note that a transaction manager that does not support timeouts will throw
* an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
*
The default is {@link #TIMEOUT_DEFAULT}.
* @return the transaction timeout
*/
default int getTimeout() {
return TIMEOUT_DEFAULT;
}
/**
* Return whether to optimize as a read-only transaction.
*
The read-only flag applies to any transaction context, whether backed
* by an actual resource transaction ({@link #PROPAGATION_REQUIRED}/
* {@link #PROPAGATION_REQUIRES_NEW}) or operating non-transactionally at
* the resource level ({@link #PROPAGATION_SUPPORTS}). In the latter case,
* the flag will only apply to managed resources within the application,
* such as a Hibernate {@code Session}.
*
This just serves as a hint for the actual transaction subsystem;
* it will not necessarily cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will
* not throw an exception when asked for a read-only transaction.
* @return {@code true} if the transaction is to be optimized as read-only
* ({@code false} by default)
* @see org.springframework.transaction.support.TransactionSynchronization#beforeCommit(boolean)
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
*/
default boolean isReadOnly() {
return false;
}
/**
* Return the name of this transaction. Can be {@code null}.
*
This will be used as the transaction name to be shown in a
* transaction monitor, if applicable (for example, WebLogic's).
*
In case of Spring's declarative transactions, the exposed name will be
* the {@code fully-qualified class name + "." + method name} (by default).
* @return the name of this transaction ({@code null} by default}
* @see org.springframework.transaction.interceptor.TransactionAspectSupport
* @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
*/
@Nullable
default String getName() {
return null;
}
// Static builder methods
/**
* Return an unmodifiable {@code TransactionDefinition} with defaults.
*
For customization purposes, use the modifiable
* {@link org.springframework.transaction.support.DefaultTransactionDefinition}
* instead.
* @since 5.2
*/
static TransactionDefinition withDefaults() {
return StaticTransactionDefinition.INSTANCE;
}
}
TransactionStatus 接口
package org.springframework.transaction;
import java.io.Flushable;
/**
* Representation of the status of a transaction.
*
* Transactional code can use this to retrieve status information,
* and to programmatically request a rollback (instead of throwing
* an exception that causes an implicit rollback).
*
*
Includes the {@link SavepointManager} interface to provide access
* to savepoint management facilities. Note that savepoint management
* is only available if supported by the underlying transaction manager.
*
* @author Juergen Hoeller
* @since 27.03.2003
* @see #setRollbackOnly()
* @see PlatformTransactionManager#getTransaction
* @see org.springframework.transaction.support.TransactionCallback#doInTransaction
* @see org.springframework.transaction.interceptor.TransactionInterceptor#currentTransactionStatus()
*/
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
/**
* Return whether this transaction internally carries a savepoint,
* that is, has been created as nested transaction based on a savepoint.
*
This method is mainly here for diagnostic purposes, alongside
* {@link #isNewTransaction()}. For programmatic handling of custom
* savepoints, use the operations provided by {@link SavepointManager}.
* @see #isNewTransaction()
* @see #createSavepoint()
* @see #rollbackToSavepoint(Object)
* @see #releaseSavepoint(Object)
*/
boolean hasSavepoint();
/**
* Flush the underlying session to the datastore, if applicable:
* for example, all affected Hibernate/JPA sessions.
*
This is effectively just a hint and may be a no-op if the underlying
* transaction manager does not have a flush concept. A flush signal may
* get applied to the primary resource or to transaction synchronizations,
* depending on the underlying resource.
*/
@Override
void flush();
}
public interface TransactionExecution {
boolean isNewTransaction();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
public interface SavepointManager {
Object createSavepoint() throws TransactionException;
void rollbackToSavepoint(Object savepoint) throws TransactionException;
void releaseSavepoint(Object savepoint) throws TransactionException;
}
声明式事务注解介绍
声明式事务注解:
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.core.annotation.AliasFor;
import org.springframework.transaction.TransactionDefinition;
/**
* Describes a transaction attribute on an individual method or on a class.
*
* At the class level, this annotation applies as a default to all methods of
* the declaring class and its subclasses. Note that it does not apply to ancestor
* classes up the class hierarchy; methods need to be locally redeclared in order
* to participate in a subclass-level annotation.
*
*
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 {@link RuntimeException} and {@link Error} but not on checked
* exceptions).
*
*
For specific information about the semantics of this annotation's attributes,
* consult the {@link org.springframework.transaction.TransactionDefinition} and
* {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs.
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @author Sam Brannen
* @since 1.2
* @see org.springframework.transaction.interceptor.TransactionAttribute
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute
* @see org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
* Alias for {@link #transactionManager}.
* @see #transactionManager
*/
@AliasFor("transactionManager")
String value() default "";
/**
* A qualifier value for the specified transaction.
*
May be used to determine the target transaction manager, matching the
* qualifier value (or the bean name) of a specific
* {@link org.springframework.transaction.TransactionManager TransactionManager}
* bean definition.
* @since 4.2
* @see #value
* @see org.springframework.transaction.PlatformTransactionManager
* @see org.springframework.transaction.ReactiveTransactionManager
*/
@AliasFor("value")
String transactionManager() 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}.
*
Exclusively designed for use with {@link Propagation#REQUIRED} or
* {@link Propagation#REQUIRES_NEW} since it only applies to newly started
* transactions. Consider switching the "validateExistingTransactions" flag to
* "true" on your transaction manager if you'd like isolation level declarations
* to get rejected when participating in an existing transaction with a different
* isolation level.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel()
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* The timeout for this transaction (in seconds).
*
Defaults to the default timeout of the underlying transaction system.
*
Exclusively designed for use with {@link Propagation#REQUIRED} or
* {@link Propagation#REQUIRES_NEW} since it only applies to newly started
* transactions.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
*/
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/**
* A boolean flag that can be set to {@code true} if the transaction is
* effectively read-only, allowing for corresponding optimizations at runtime.
*
Defaults to {@code false}.
*
This just serves as a hint for the actual transaction subsystem;
* it will not necessarily cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will
* not throw an exception when asked for a read-only transaction
* but rather silently ignore the hint.
* @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
*/
boolean readOnly() default false;
/**
* Defines zero (0) or more exception {@link Class classes}, which must be
* subclasses of {@link Throwable}, indicating which exception types must cause
* a transaction rollback.
*
By default, a transaction will be rolling back on {@link RuntimeException}
* and {@link Error} but not on checked exceptions (business exceptions). See
* {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)}
* for a detailed explanation.
*
This is the preferred way to construct a rollback rule (in contrast to
* {@link #rollbackForClassName}), matching the exception class and its subclasses.
*
Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}.
* @see #rollbackForClassName
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
*/
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.
*
This can be a substring of a fully qualified class name, with no wildcard
* support at present. For example, a value of {@code "ServletException"} would
* match {@code javax.servlet.ServletException} and its subclasses.
*
NB: Consider carefully how specific the pattern is and whether
* to include package information (which isn't mandatory). For example,
* {@code "Exception"} will match nearly anything and will probably hide other
* rules. {@code "java.lang.Exception"} would be correct if {@code "Exception"}
* were meant to define a rule for all checked exceptions. With more unusual
* {@link Exception} names such as {@code "BaseBusinessException"} there is no
* need to use a FQN.
*
Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)}.
* @see #rollbackFor
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
*/
String[] rollbackForClassName() default {};
/**
* Defines zero (0) or more exception {@link Class Classes}, which must be
* subclasses of {@link Throwable}, indicating which exception types must
* not cause a transaction rollback.
*
This is the preferred way to construct a rollback rule (in contrast
* to {@link #noRollbackForClassName}), matching the exception class and
* its subclasses.
*
Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}.
* @see #noRollbackForClassName
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
*/
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 not
* cause a transaction rollback.
*
See the description of {@link #rollbackForClassName} for further
* information on how the specified names are treated.
*
Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)}.
* @see #noRollbackFor
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
*/
String[] noRollbackForClassName() default {};
}
传播行为的枚举类:
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 {
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
NEVER(TransactionDefinition.PROPAGATION_NEVER),
NESTED(TransactionDefinition.PROPAGATION_NESTED);
private final int value;
Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
隔离级别的枚举类:
package org.springframework.transaction.annotation;
import org.springframework.transaction.TransactionDefinition;
/**
* Enumeration that represents transaction isolation levels for use
* with the {@link Transactional} annotation, corresponding to the
* {@link TransactionDefinition} interface.
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @since 1.2
*/
public enum Isolation {
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
private final int value;
Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
事务属性详解
Spring事务传播行为详解
嵌套事务 - 百度百科
事务传播行为
常用的事务传播行为有:
PROPAGATION_REQUIRED(默认)
PROPAGATION_REQUIRES_NEW
PROPAGATION_NESTED
事务传播行为是为了解决业务层方法之间相互调用的事务问题。
传播行为 | 描述 | 回滚 |
---|---|---|
PROPAGATION_REQUIRED | 如果外部方法没有开启事务,则创建一个新事务; 如果外部方法有开启事务,则参与外部事务; |
任何方法发生异常都会导致事务回滚 |
PROPAGATION_REQUIRES_NEW | 如果外部方法开启事务,则挂起外部事务。并且总是创建新事务。 | 如果外部方法发生异常,只会回滚外部事务; 如果内部方法发生异常,则会回滚内部事务,如果外部方法未捕获异常,则会同时回滚外部事务; |
PROPAGATION_NESTED | 如果外部方法没有开启事务,则创建新事务; 如果外部方法开启事务,则内部事务作为外部事务的子事务; |
嵌套事务:外部事务回滚时,子事务会跟着回滚;子事务可以独立的提交或回滚,而不影响外部事务。 |
事务隔离级别
并发异常:
更新异常:
* (回滚导致的)第一类丢失更新
* (提交导致的)第二类丢失更新
读取异常:
* 脏读(读取其他事务未提交的数据)
* 不可重复读(两次读取同一行数据却得到不同的值)
* 幻读(两次读取同一条件的数据却得到不同的结果集)
隔离级别:
隔离级别 | 解决的异常 |
---|---|
读未提交 | 所有的读取异常都会出现 |
读已提交 | 不会出现脏读,会出现不可重复读、幻读 |
可重复读 | 不会出现脏读和不可重复读,会出现幻读 |
串行化 | 所有的读取异常都不会出现 |
实现机制:
悲观锁:
* 共享锁
* 排他锁
乐观锁
更新异常:
// 数据库实现了悲观锁,在更新数据时对数据加上排他锁,所以不会出现更新异常。
// 但要避免应用逻辑的更新异常
//
// 以下代码不是原子性的,所以会导致第二类丢失更新
public void UpdateException(){
Data data = selectData();
// process data
updateData(data);
}
MySQL 的可重复读:
1. MySQL 默认隔离级别是可重复读
2. MySQL InnoDB 的可重复读通过临键锁解决了幻读问题
事务超时
事务被允许的最长执行时间,超过该时间将自动回滚。
只读事务
将多条查询语句放在一个事务中,保证整个查询的一致性。
回滚规则
在声明式注解有两个参数可以定义回滚规则:默认是遇到 Error
和 RuntimeException
时回滚事务
/**
* Defines zero (0) or more exception {@link Class classes}, which must be
* subclasses of {@link Throwable}, indicating which exception types must cause
* a transaction rollback.
* By default, a transaction will be rolling back on {@link RuntimeException}
* and {@link Error} but not on checked exceptions (business exceptions). See
* {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)}
* for a detailed explanation.
*
This is the preferred way to construct a rollback rule (in contrast to
* {@link #rollbackForClassName}), matching the exception class and its subclasses.
*
Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}.
* @see #rollbackForClassName
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
*/
Class extends Throwable>[] rollbackFor() default {};
/**
* Defines zero (0) or more exception {@link Class Classes}, which must be
* subclasses of {@link Throwable}, indicating which exception types must
* not cause a transaction rollback.
*
This is the preferred way to construct a rollback rule (in contrast
* to {@link #noRollbackForClassName}), matching the exception class and
* its subclasses.
*
Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}.
* @see #noRollbackForClassName
* @see org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn(Throwable)
*/
Class extends Throwable>[] noRollbackFor() default {};