springboot/spring事务传播机制

前置学习:springboot事务_springboot启动事务-CSDN博客

PlatformTransactionManager#getTransaction

PROPAGATION_REQUIRED 

如果存在事务,就开启当前事务,如果不存在事务,则创建事务

1、存在事务的场景,就返回当前的TransactionStatus

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

2、不存在事务的场景则创建一个新事务:

org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction

PROPAGATION_REQUIRES_NEW

总是先挂起当前事务,并且创建并且开启一个新事务。

1、存在当前事务的时候,先挂起当前事务,会存档一个SuspendedResourcesHolder,用来存储被挂起的事务信息。然后开启一个新事务startTransaction。

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
   if (debugEnabled) {
      logger.debug("Suspending current transaction, creating new transaction with name [" +
            definition.getName() + "]");
   }
   SuspendedResourcesHolder suspendedResources = suspend(transaction);
   try {
      return startTransaction(definition, transaction, debugEnabled, suspendedResources);
   }
   catch (RuntimeException | Error beginEx) {
      resumeAfterBeginException(transaction, suspendedResources, beginEx);
      throw beginEx;
   }
}
org.springframework.transaction.support.AbstractPlatformTransactionManager#suspend
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
   if (TransactionSynchronizationManager.isSynchronizationActive()) {
      List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
      try {
         Object suspendedResources = null;
         if (transaction != null) {
            suspendedResources = doSuspend(transaction);
         }
         String name = TransactionSynchronizationManager.getCurrentTransactionName();
         TransactionSynchronizationManager.setCurrentTransactionName(null);
         boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
         TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
         Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
         TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
         boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
         TransactionSynchronizationManager.setActualTransactionActive(false);
         return new SuspendedResourcesHolder(
               suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
      }
      catch (RuntimeException ex) {
         // doSuspend failed - original transaction is still active...
         doResumeSynchronization(suspendedSynchronizations);
         throw ex;
      }
      catch (Error err) {
         // doSuspend failed - original transaction is still active...
         doResumeSynchronization(suspendedSynchronizations);
         throw err;
      }
   }
   else if (transaction != null) {
      // Transaction active but no synchronization active.
      Object suspendedResources = doSuspend(transaction);
      return new SuspendedResourcesHolder(suspendedResources);
   }
   else {
      // Neither transaction nor synchronization active.
      return null;
   }
}

2、不存在当前事务的情况

当前不存在事务的时候,从ThreadLocal中取出当前事务,并且进行存档一个SuspendedResourcesHolder,同时设置当前事务的名称、隔离级别、只读全部为空。SuspendedResourcesHolder会作为旧的事务存档到当前事务中。

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction 

else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	SuspendedResourcesHolder suspendedResources = suspend(null);
	if (debugEnabled) {
		logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
	}
	try {
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		doBegin(transaction, definition);
		prepareSynchronization(status, definition);
		return status;
	}catch (RuntimeException ex) {
		resume(null, suspendedResources);
		throw ex;
	}catch (Error err) {
		resume(null, suspendedResources);
		throw err;
	}
}

ROPAGATION_NESTED

如果已经存在事务,那么运行在在这个嵌套事务中。如果不存在事务,则创建一个新的事务。

Mysql使用safepoint完成事务的部分回滚,语法如下;

1.定义保存点---SAVEPOINT 保存点名;

2.回滚到指定保存点---ROLLBACK TO SAVEPOINT 保存点名:

1、如果已经存在当前事务,则运行在当前事务中,

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction。

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	if (!isNestedTransactionAllowed()) {
		throw new NestedTransactionNotSupportedException(
						"Transaction manager does not allow nested transactions by default - " +
						"specify 'nestedTransactionAllowed' property with value 'true'");
	}
	if (debugEnabled) {
		logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
	}
	if (useSavepointForNestedTransaction()) {
		// Create savepoint within existing Spring-managed transaction,
		// through the SavepointManager API implemented by TransactionStatus.
		// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
        prepareTransactionStatus第三个参数代表newTransaction为false,代表在startTransaction是不会再创建一个新的事务的。
		DefaultTransactionStatus status =
						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
				status.createAndHoldSavepoint();
				return status;
	}else {
		// Nested transaction through nested begin and commit/rollback calls.
		// Usually only for JTA: Spring synchronization might get activated here
		// in case of a pre-existing JTA transaction.
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, null);
		doBegin(transaction, definition);
		prepareSynchronization(status, definition);
		return status;
	}
}

2、如果不存在当前事务,则挂起当前事务(所有事务信息全挂为null,并且不持有任何connect连接),并且创建一个新的事务,保留旧事务的suspendedResources。

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction 

else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	SuspendedResourcesHolder suspendedResources = suspend(null);
	if (debugEnabled) {
		logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
	}
	try {
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		doBegin(transaction, definition);
		prepareSynchronization(status, definition);
		return status;
	}catch (RuntimeException ex) {
		resume(null, suspendedResources);
		throw ex;
	}catch (Error err) {
		resume(null, suspendedResources);
		throw err;
	}
}

PROPAGATION_SUPPORTS

如果已经存在事务,那么使用当前事务。如果没有事务,则非事务的执行。

这个传播机制在源码上来说,是根本不做任何处理的,基本上走的默认预备事务处理(prepareTransactionStatus)

1、存在事务的场景,沿用旧事务

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);

2、不存在事务的场景,则返回一个默认的事务,但是第二个值为null,实际就是以非事务运行。

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);

PROPAGATION_NOT_SUPPORTED

总是非事务地执行,并挂起任何存在的事务。

1、已存在当前事务的场景:不会创建新的事务,并且挂起当前事务,记录一个存档

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
	if (debugEnabled) {
		logger.debug("Suspending current transaction");
	}
	Object suspendedResources = suspend(transaction);
	boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
	return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}

2、不存在事务的场景,则返回一个默认的事务,但是第二个值为null,实际就是以非事务运行。

return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);

PROPAGATION_MANDATORY

必须在一个事务中运行,如果没有事务,将抛出异常。(这一块有争议)

这个实现就非常简单了。

只是判断在当前事务,没有事务的情况,立马返回一个异常。

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction


if (isExistingTransaction(transaction)) {
   // Existing transaction found -> check propagation behavior to find out how to behave.
   return handleExistingTransaction(definition, transaction, debugEnabled);
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
   throw new IllegalTransactionStateException(
         "No existing transaction found for transaction marked with propagation 'mandatory'");
}

PROPAGATION_NEVER

总是非事务地执行,如果在事务中运行,则抛出异常。

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值