Spring 事务分析总结

基于 Spring事务分析总结 - JavaGuide 的总结

[TOC]

Spring 事务分析总结

事务的概念

什么是事务:

事务是由一组SQL语句组成的逻辑执行单元,这些语句要么全部执行,要么全部不执行。

事务的四大特性(ACID):

* 原子性
* 一致性
* 隔离性
* 持久性

隔离级别:

* 读未提交(脏读、不可重复读、幻读)
* 读已提交(不可重复读、幻读)
* 可重复读(幻读)
* 串行化

MySQL 如何保证原子性:

回滚日志(undo log)

MySQL 如何保证持久性:

重做日志(redo log)

Spring 对事务的支持

Spring 支持的两种事务管理的方式

Spring 支持两种事务管理的方式:

* 声明式事务
* 编程式事务

编程式事务

通过 TransactionManagerTransactionTemplate 手动管理事务:

@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[] 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[] 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 的可重复读通过临键锁解决了幻读问题

事务超时

事务被允许的最长执行时间,超过该时间将自动回滚。

只读事务

将多条查询语句放在一个事务中,保证整个查询的一致性。

回滚规则

在声明式注解有两个参数可以定义回滚规则:默认是遇到 ErrorRuntimeException 时回滚事务

/**
 * 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[] 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[] noRollbackFor() default {};

你可能感兴趣的:(Spring 事务分析总结)