Spring事务

彻底搞懂 MySQL 事务的隔离级别

参考文章:https://developer.aliyun.com/article/743691

本文介绍了事务中的脏读,不可重复读,幻读等概念。
事务的隔离级别:读未提交、读已提交、可重复读以及可串行化
查看当前会话隔离级别:
SHOW VARIABLES LIKE 'transaction_isolation';
SELECT @@transaction_isolation;

spring事务简介(主要介绍了spring事务的概念)

https://www.tutorialspoint.com/spring/spring_transaction_management.htm

spring事务传播性

参考文章(非常经典):https://dzone.com/articles/spring-transaction-propagation

    REQUIRED(0), // 默认配置
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
  1. NEVER(5):
    Does not support a current transaction; throws an exception if a current transaction exists.
  2. MANDATORY(2):
    Supports a current transaction; throws an exception if no current transaction exists.
  3. NOT_SUPPORTED(4):
    Does not support a current transaction; rather always execute nontransactionally.
  4. SUPPORTS(1):
    Supports a current transaction; executes non-transactionally if none exists.
  5. REQUIRED(0):
    Supports a current transaction; creates a new one if none exists.
  6. REQUIRES_NEW(3):
    Creates a new transaction, suspending the current transaction if one exists.
  7. NESTED(6):
    Executes within a nested transaction if a current transaction exists.

事务传播的源代码分析

执行路径
TransactionInterceptor->invoke->invokeWithinTransaction->createTransactionIfNecessary->
AbstractPlatformTransactionManager.getTransaction

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
        Object transaction = this.doGetTransaction();
        boolean debugEnabled = this.logger.isDebugEnabled();
        if(definition == null) {
            definition = new DefaultTransactionDefinition();
        }

        if(this.isExistingTransaction(transaction)) {
            return this.handleExistingTransaction((TransactionDefinition)definition, transaction, debugEnabled);
        } else if(((TransactionDefinition)definition).getTimeout() < -1) {
            throw new InvalidTimeoutException("Invalid transaction timeout", ((TransactionDefinition)definition).getTimeout());
        } else if(((TransactionDefinition)definition).getPropagationBehavior() == 2) {
            throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation \'mandatory\'");
        } else if(((TransactionDefinition)definition).getPropagationBehavior() != 0 && ((TransactionDefinition)definition).getPropagationBehavior() != 3 && ((TransactionDefinition)definition).getPropagationBehavior() != 6) {
            if(((TransactionDefinition)definition).getIsolationLevel() != -1 && this.logger.isWarnEnabled()) {
                this.logger.warn("Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: " + definition);
            }

            boolean newSynchronization1 = this.getTransactionSynchronization() == 0;
            return this.prepareTransactionStatus((TransactionDefinition)definition, (Object)null, true, newSynchronization1, debugEnabled, (Object)null);
        } else {
            AbstractPlatformTransactionManager.SuspendedResourcesHolder newSynchronization = this.suspend((Object)null);
            if(debugEnabled) {
                this.logger.debug("Creating new transaction with name [" + ((TransactionDefinition)definition).getName() + "]: " + definition);
            }

            try {
                boolean ex = this.getTransactionSynchronization() != 2;
                DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, ex, debugEnabled, newSynchronization);
                this.doBegin(transaction, (TransactionDefinition)definition);
                this.prepareSynchronization(status, (TransactionDefinition)definition);
                return status;
            } catch (Error | RuntimeException var7) {
                this.resume((Object)null, newSynchronization);
                throw var7;
            }
        }
    }

源代码中通过isExistingTransaction首先判断是否已经存在事务。

  1. 物理事务不存在
    1.1 如果事务传播类型为2(MANDATORY),则抛出异常。该行为和我们上面解释的相吻合:Supports a current transaction; throws an exception if no current transaction exists.(如果当前物理事务不存在,则抛出异常)
    1.2 然后判读事务类型是否为0,3,6。也就是1,4,5会进入该分支(SUPPORTS,NOT_SUPPORTED,NEVER)。我们详细了解1,4,5类型的解释就知道,当当前物理事务不存在时,下面的处理逻辑不会按照事务处理,所以随后抛出一个警告:Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored(自定义了事务的隔离级别,但是没有真正的事务初始化,定义的隔离级别没什么卵用)
    1.3 最后时事务不存在时,对事务类型0,3,6的执行(REQUIRED,REQUIRES_NEW,NESTED)。先挂起原先的物理事务(this.suspend((Object)null)),然后新建逻辑事务(this.newTransactionStatus),最后执行逻辑事务。这和0,3,6的语义相吻合。
  2. 物理事务存在的情景
 private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException {
        if(definition.getPropagationBehavior() == 5) {
            throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation \'never\'");
        } else {
            AbstractPlatformTransactionManager.SuspendedResourcesHolder newSynchronization3;
            boolean isoConstants2;
            if(definition.getPropagationBehavior() == 4) {
                if(debugEnabled) {
                    this.logger.debug("Suspending current transaction");
                }

                newSynchronization3 = this.suspend(transaction);
                isoConstants2 = this.getTransactionSynchronization() == 0;
                return this.prepareTransactionStatus(definition, (Object)null, false, isoConstants2, debugEnabled, newSynchronization3);
            } else if(definition.getPropagationBehavior() == 3) {
                if(debugEnabled) {
                    this.logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]");
                }

                newSynchronization3 = this.suspend(transaction);

                try {
                    isoConstants2 = this.getTransactionSynchronization() != 2;
                    DefaultTransactionStatus status = this.newTransactionStatus(definition, transaction, true, isoConstants2, debugEnabled, newSynchronization3);
                    this.doBegin(transaction, definition);
                    this.prepareSynchronization(status, definition);
                    return status;
                } catch (Error | RuntimeException var7) {
                    this.resumeAfterBeginException(transaction, newSynchronization3, var7);
                    throw var7;
                }
            } else {
                boolean newSynchronization1;
                if(definition.getPropagationBehavior() == 6) {
                    if(!this.isNestedTransactionAllowed()) {
                        throw new NestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - specify \'nestedTransactionAllowed\' property with value \'true\'");
                    } else {
                        if(debugEnabled) {
                            this.logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
                        }

                        if(this.useSavepointForNestedTransaction()) {
                            DefaultTransactionStatus newSynchronization2 = this.prepareTransactionStatus(definition, transaction, false, false, debugEnabled, (Object)null);
                            newSynchronization2.createAndHoldSavepoint();
                            return newSynchronization2;
                        } else {
                            newSynchronization1 = this.getTransactionSynchronization() != 2;
                            DefaultTransactionStatus isoConstants1 = this.newTransactionStatus(definition, transaction, true, newSynchronization1, debugEnabled, (Object)null);
                            this.doBegin(transaction, definition);
                            this.prepareSynchronization(isoConstants1, definition);
                            return isoConstants1;
                        }
                    }
                } else {
                    if(debugEnabled) {
                        this.logger.debug("Participating in existing transaction");
                    }

                    if(this.isValidateExistingTransaction()) {
                        if(definition.getIsolationLevel() != -1) {
                            Integer newSynchronization = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                            if(newSynchronization == null || newSynchronization.intValue() != definition.getIsolationLevel()) {
                                Constants isoConstants = DefaultTransactionDefinition.constants;
                                throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (newSynchronization != null?isoConstants.toCode(newSynchronization, "ISOLATION_"):"(unknown)"));
                            }
                        }

                        if(!definition.isReadOnly() && TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                            throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is");
                        }
                    }

                    newSynchronization1 = this.getTransactionSynchronization() != 2;
                    return this.prepareTransactionStatus(definition, transaction, false, newSynchronization1, debugEnabled, (Object)null);
                }
            }
        }
    }

2.1 如果事务传播类型为5(NEVER),则抛出异常。这和上述解释吻合:Does not support a current transaction; throws an exception if a current transaction exists.(如果当前物理事务存在,则抛出异常)
2.2 如果事务传播类型为4(NOT_SUPPORTED),则挂起:Does not support a current transaction; rather always execute nontransactionally.
2.3 如果事务传播类型为3(REQUIRES_NEW),先挂起,再创建新的事务:Creates a new transaction, suspending the current transaction if one exists.
2.4 如果事务传播类型为6(NESTED).先判断是否支持内嵌事务,不支持抛出异常:Transaction manager does not allow nested transactions by default。然后判断是否使用了savePoint,如果是createAndHoldSavepoint,否则创建事务并执行。
NESTED acts like REQUIRED_NEW, only it uses savepoints between nested invocations. In other words, inner logical transactions may roll back independently of outer logical transactions.

你可能感兴趣的:(Spring事务)