Spring事务分析
Spring事务最佳实践:
1. Spring事务不要用@Transaction(PS:如果用的话最好加到service层的方法上面而不要加到dao层、Controller层),会有一些情况导致事务回滚失败。
2. 最好使用代码来实现事务管理
3. 不要在事务里面执行RPC、HTTP请求等操作,避免由于网络抖动导致出现耗时事务的问题,耗时事务会长时间锁数据库.
如果避免不了那么这就是一个分布式事务的问题了。
事务的传播性:
1.REQUIRED:方法在一个事务中执行,如果调用的方法已经在一个事务中,则使用该事务,否则将创建一个新的事务。(默认的)
2.MANDATORY:方法必须在一个事务中执行,也就是说调用的方法必须已经有一个事务,否则新抛出一个错误(ERROR)。
3.REQUIRESNEW:方法将在一个新的事务中执行,如果调用的方法已经在一个事务中,则暂停旧的事务。
4.SUPPORTS:如果方法在一个事务中被调用,则使用该事务,否则不使用事务。
5.NOT_SUPPORTED:如果方法在一个事务中被调用,将抛出一个错误(ERROR)
事务的实现原理:
使用编程式事务代码如下:
PlatformTransactionManager platformTransactionManager=new DataSourceTransactionManager(); TransactionTemplate transactionTemplate=new TransactionTemplate(); //设置事务的超时时间 transactionTemplate.setTimeout(5000); //事务的隔离级别 transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); //事务的传播行为 transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); //是否为只读事务 transactionTemplate.setReadOnly(false); //获取事务 TransactionStatus transactionStatus=platformTransactionManager.getTransaction(transactionTemplate); try{ //数据库操作... //提交事务 platformTransactionManager.commit(transactionStatus); }catch (Exception ex){ //回滚事务 platformTransactionManager.rollback(transactionStatus); }
这里我们先分析getTransaction方法:
@Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { // Use defaults if no transaction definition given. TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); //获取事务信息DataSourceTransactionObject,这里面主要包含事务的保存点,和连接上下文 Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); //判断当前线程的连接是否开启了事务txObject.getConnectionHolder().isTransactionActive() if (isExistingTransaction(transaction)) { //根据事务的传播性是否要开启新事务 return handleExistingTransaction(def, transaction, debugEnabled); } //事务的超时时间不能少于默认的 if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def); } try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( def, transaction, true, newSynchronization, debugEnabled, suspendedResources); //这里开始事务 doBegin(transaction, def); //绑定事务相关信息到当前线程 prepareSynchronization(status, def); return status; } catch (RuntimeException | Error ex) { resume(null, suspendedResources); throw ex; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) { logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + def); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null); } }
我们真正分析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); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); //从当前线程获取绑定的连接 con = txObject.getConnectionHolder().getConnection(); //初始化事务 //1、设置是否只读:con.setReadOnly(true); //2、设置隔离级别:con.setTransactionIsolation(definition.getIsolationLevel()); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); txObject.setReadOnly(definition.isReadOnly()); //设置为手动提交事务 if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } //发送事务只读指令 stmt.executeUpdate("SET TRANSACTION READ ONLY"); prepareTransactionalConnection(con, definition); //设置当前连接的事务为激活状态,作为后面判断是否存在事务的标识 txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // Bind the connection holder to the thread. 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); } }

浙公网安备 33010602011771号