Spring事务隔离级别是通过底层数据库的事务管理机制来实现的。事务隔离级别定义了在事务并发执行时,一个事务所做的改变对其他事务的可见性。Spring框架本身不直接实现这些隔离级别,而是利用底层数据库(如MySQL、PostgreSQL、Oracle等)的支持。下面是一些关键概念和实现方式:
-
事务隔离级别:
- READ_UNCOMMITTED(未提交读) :最低的隔离级别,允许读取未提交的数据,可能导致脏读、不可重复读和幻读。
- READ_COMMITTED(已提交读) :只读取已提交的数据,可以防止脏读,但不能防止不可重复读和幻读。
- REPEATABLE_READ(可重复读) :确保在同一个事务中多次读取时数据是一致的,可以防止脏读和不可重复读,但不能防止幻读。
- SERIALIZABLE(可串行化) :最高的隔离级别,通过强制事务顺序执行来防止脏读、不可重复读和幻读。
-
Spring中的配置: 在Spring中,你可以通过
@Transactional注解来设置事务的隔离级别。例如:@Transactional(isolation = Isolation.READ_COMMITTED) public void someTransactionalMethod() { // 方法实现 } -
底层实现: Spring的事务管理器(如
DataSourceTransactionManager)会将配置的隔离级别传递到底层数据库驱动。具体步骤如下:- 当事务开始时,Spring的事务管理器会通过JDBC连接设置事务的隔离级别。
- 这通常是通过标准的JDBC API完成的,例如调用
Connection.setTransactionIsolation(int level)方法。 - 底层数据库接收到这个请求后,会根据自身的实现调整隔离级别。例如,在MySQL中,这可以通过
SET TRANSACTION ISOLATION LEVELSQL语句来实现。
-
数据库支持: 不同的数据库对事务隔离级别的支持和实现方式可能有所不同。一般来说,关系型数据库都会遵循SQL标准,但具体的性能优化和实现细节会有所差异。例如:
- MySQL使用InnoDB存储引擎时,支持所有标准的事务隔离级别,并可以通过配置文件或运行时设置进行调整。
- PostgreSQL也提供了全面的事务隔离级别支持,并在其MVCC(多版本并发控制)机制下有详细的实现。
AbstractPlatformTransactionManager核心源码分析
AbstractPlatformTransactionManager 是 Spring 事务管理框架中的一个核心抽象类,提供了事务处理的基本骨架。许多具体的事务管理器(如 DataSourceTransactionManager)都继承自这个抽象类,并实现了各自特定的事务处理逻辑。在这个抽象类中,定义了一系列模板方法和基本的事务控制逻辑。
核心方法解析
1. getTransaction()
负责获取当前事务状态或创建一个新的事务。
@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
Object transaction = doGetTransaction();
// Determine if we need to start a new transaction.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
definition = new DefaultTransactionDefinition();
}
if (isExistingTransaction(transaction)) {
return handleExistingTransaction(definition, transaction, debugEnabled);
}
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
AbstractPlatformTransactionManager.SuspendedResourcesHolder suspendedResources = suspend(null);
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 | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
- 获取事务对象:调用
doGetTransaction()方法获取当前的事务对象。 - 判断是否存在事务:检查事务对象是否已经存在事务,通过
isExistingTransaction(transaction)方法。 - 处理现有事务:如果存在事务,则通过
handleExistingTransaction()方法处理。 - 启动新事务:如果没有现有事务,根据事务定义启动一个新事务,包括设置超时、挂起现有事务等。
2. commit()
负责提交事务。
@Override
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processCommit(defStatus);
}
- 检查事务状态:确保事务当前是未完成状态,否则抛出异常。
- 调用
processCommit方法:处理事务提交的具体逻辑。
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
//初始化标志变量 `beforeCompletionInvoked`,用于跟踪是否已经触发了完成前处理(`beforeCompletion`)
boolean beforeCompletionInvoked = false;
try {
// 初始化标志变量 `unexpectedRollback`,用于标记是否发生了意外的回滚。
boolean unexpectedRollback = false;
prepareForCommit(status); //为提交事务做准备。这通常用于检查和设置一些需要提交的资源或状态。
triggerBeforeCommit(status); //通知所有已注册的事务同步器(`TransactionSynchronization`)即将提交事务
triggerBeforeCompletion(status); //通知所有已注册的事务同步器即将完成事务
beforeCompletionInvoked = true; //设置为 `true`,表示已经触发了完成前处理
if (status.hasSavepoint()) { //如果事务有保存点(`savepoint`),则释放保存点。
status.releaseHeldSavepoint();
} else if (status.isNewTransaction()) { //如果是一个新事务,调用 `doCommit(status)` 方法执行实际的提交操作。
doCommit(status);
} else if (isFailEarlyOnGlobalRollbackOnly()) { //如果配置了全局回滚检查并且需要提前失败,则标记 `unexpectedRollback` 为 `true`
unexpectedRollback = true;
} else if (status.isGlobalRollbackOnly()) { //如果事务被标记为仅回滚(`globalRollbackOnly`),则标记 `unexpectedRollback` 为 `true`
unexpectedRollback = true;
}
// 如果没有发生意外的回滚,调用 `triggerAfterCommit(status)` 方法,触发提交后的处理。
if (!unexpectedRollback) {
//通知所有已注册的事务同步器事务已经成功提交。
triggerAfterCommit(status);
}
} catch (UnexpectedRollbackException ex) {
//通知所有已注册的事务同步器事务已经完成,无论是提交还是回滚。
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
} catch (TransactionException ex) {
if (beforeCompletionInvoked) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
} finally {
//- 清理事务完成后的资源,包括重置事务状态、解除资源绑定以及恢复挂起的事务等。
cleanupAfterCompletion(status);
}
}
- 准备提交:调用
prepareForCommit(status)方法。 - 触发提交前事件:包括
triggerBeforeCommit(status)和triggerBeforeCompletion(status)。 - 执行提交:调用
doCommit(status)方法。 - 触发提交后事件:包括
triggerAfterCommit(status)和triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED)。 - 清理工作:调用
cleanupAfterCompletion(status)方法。
异常处理
UnexpectedRollbackException:如果捕获到意外回滚异常(UnexpectedRollbackException),将unexpectedRollback标记为true并重新抛出该异常。TransactionException:如果捕获到一般的事务异常(TransactionException),检查是否已经触发了完成前处理,如果是,则调用triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN)处理完成后逻辑,并重新抛出异常。RuntimeException或Error:捕获运行时异常或错误,同样检查是否已经触发了完成前处理,如果是,则调用triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN)处理完成后逻辑,并重新抛出异常。
3. rollback()
负责回滚事务。
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus);
}
- 检查事务状态:确保事务当前是未完成状态,否则抛出异常。
- 调用
processRollback方法处理具体的回滚逻辑。
private void processRollback(DefaultTransactionStatus status, boolean unexpected) throws TransactionException {
try {
boolean unexpectedRollback = unexpected;
try {
triggerBeforeCompletion(status);
if (status.hasSavepoint()) {
status.rollbackToHeldSavepoint();
} else if (status.isNewTransaction()) {
doRollback(status);
} else {
if (status.hasTransaction()) {
if (status.isGlobalRollbackOnly() || unexpectedRollback) {
doSetRollbackOnly(status);
}
} else {
logger.debug("Should roll back but has no transaction.");
}
}
} catch (UnexpectedRollbackException ex) {
unexpectedRollback = true;
throw ex;
} catch (TransactionException ex) {
if (status.isDebug()) {
logger.debug("Transactional code threw unexpected exception", ex);
}
throw ex;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
} finally {
cleanupAfterCompletion(status);
}
}
-
触发提交前事件:调用
triggerBeforeCompletion(status)函数。 -
执行回滚:
- 保存点回滚:如果有保存点,调用
rollbackToHeldSavepoint()方法回滚到保存点。 - 新事务回滚:如果是一个新的事务,通过
doRollback(status)进行回滚。 - 全局回滚:如果是全局回滚或意外回滚,通过
doSetRollbackOnly(status)设置为仅回滚。
- 保存点回滚:如果有保存点,调用
-
触发回滚后事件:调用
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK)函数。 -
清理工作:调用
cleanupAfterCompletion(status)函数。
模板方法概述
AbstractPlatformTransactionManager 使用了模板方法模式,定义了一些抽象方法,让子类来实现具体的事务操作逻辑。主要有以下几个:
doGetTransaction()获取事务对象。由子类实现,用于返回实际的事务对象。doBegin(Object transaction, TransactionDefinition definition)开始事务。由子类实现,用于根据事务定义启动一个新事务。doCommit(DefaultTransactionStatus status)提交事务。由子类实现,执行事务提交的实际逻辑。doRollback(DefaultTransactionStatus status)回滚事务。由子类实现,执行事务回滚的实际逻辑。doSetRollbackOnly(DefaultTransactionStatus status)设置事务为仅回滚状态。由子类实现,当需要标记事务只能回滚时调用。
事务同步机制
AbstractPlatformTransactionManager 还提供了事务同步机制,可以在事务生命周期内绑定和管理资源:
prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition)准备事务同步,注册事务同步器。triggerBeforeCommit(DefaultTransactionStatus status)在事务提交前触发事务同步器中的相应方法。triggerBeforeCompletion(DefaultTransactionStatus status)在事务完成前触发事务同步器中的相应方法。triggerAfterCommit(DefaultTransactionStatus status)在事务提交后触发事务同步器中的相应方法。triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus)在事务完成后触发事务同步器中的相应方法,无论是提交还是回滚。
DataSourceTransactionManager核心源码分析
DataSourceTransactionManager 是 Spring 框架中用于管理 JDBC 事务的核心组件。它主要负责协调数据库连接、定义事务边界以及处理事务的提交和回滚。下面我们通过分析其核心源码,详细解释其工作原理。
1. doBegin 方法
doBegin 方法负责开始一个新的事务,它会获取数据库连接并设置事务的必要属性,如隔离级别、只读状态等。
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 如果当前事务没有连接持有者(即当前事务对象还没有绑定数据库连接),或者连接持有者已经同步到事务(说明可能处于重入状态,或其他特殊情况需要重新获取连接)。
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
// 将 `ConnectionHolder` 与当前事务同步,并从 `ConnectionHolder` 中获取实际的数据库连接赋值给 `con`。
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
// 设置事务的隔离级别,并保存之前的隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
// 设置只读属性
if (definition.isReadOnly()) {
try {
con.setReadOnly(true);
} catch (SQLException ex) {
logger.debug("Could not set JDBC Connection read-only", ex);
}
}
// 设置事务的超时时间
if (txObject.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(txObject.getTimeout());
}
// 将连接持有者绑定到当前线程
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
2. doCommit 方法
doCommit 方法负责提交事务。
@Override
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
}
try {
// 提交 JDBC 事务
con.commit();
} catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
3. doRollback 方法
doRollback 方法负责回滚事务。
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
// 回滚 JDBC 事务
con.rollback();
} catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
4. doCleanupAfterCompletion 方法
doCleanupAfterCompletion 方法在事务完成后清理资源。
@Override
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
// 从当前线程解绑连接持有者
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
// 重置只读状态和隔离级别
try {
Connection con = txObject.getConnectionHolder().getConnection();
if (con != null && !con.isClosed()) {
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);
}
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
}
} catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
}
txObject.getConnectionHolder().clear();
}
总结
DataSourceTransactionManager通过这些核心方法实现了对事务的管理:
doBegin:获取数据库连接并配置事务。doCommit:提交事务。doRollback:回滚事务。doCleanupAfterCompletion:在事务完成后清理资源。