彻底搞懂 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);
- NEVER(5):
Does not support a current transaction; throws an exception if a current transaction exists. - MANDATORY(2):
Supports a current transaction; throws an exception if no current transaction exists. - NOT_SUPPORTED(4):
Does not support a current transaction; rather always execute nontransactionally. - SUPPORTS(1):
Supports a current transaction; executes non-transactionally if none exists. - REQUIRED(0):
Supports a current transaction; creates a new one if none exists. - REQUIRES_NEW(3):
Creates a new transaction, suspending the current transaction if one exists. - 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 如果事务传播类型为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的语义相吻合。 - 物理事务存在的情景
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.