我在多线程应用程序中使用Spring-tx-4.0.9,并且在线程被OutOfMemory杀死后出现“停滞”事务的问题。
每个帖子都要求PlatformTransactionManager
(实现org.springframework.jdbc.datasource.DataSourceTransactionManager
)通过TransactionTemplate
进行交易。传播是必需的。此模板具有超时设置。事务状态由应用程序管理,毕竟工作完成,然后线程调用commit。这会将事务返回到PlatformTransactionManager
,并且几乎每次都释放与DB的连接(在DB中,此连接的会话主要是释放)
但是如果线程被OutOfMemory杀死,那么底层事务将返回到内部事务池,而另一个线程可以获取此“已损坏”事务。此事务具有从第一次设置的超时,即使新线程调用TM以获得与new TransactionTemplate
的事务,也无法重置。因此,在此超时到期后,每个事务请求都会抛出TransactionTimedOutException
。
仅PlatformTransactionManager
上的可用方法为getTransaction
,commit
和rollback
。
方法getTransaction
可以返回新的或以前的事务。从返回的TransactionStatus
实例,我能够检测到新的或停滞的事务,但我无法释放它。
方法rollback
设置标记isRollbackOnly
,但事务仍未释放,getTransaction
返回停止。如果我按照JavaDoc的建议调用commit
,那么没有任何改变,交易仍然被挂起。
如果我使用传播REQUIRES_NEW
,那么“已损坏”事务将被暂停,这会解决TransactionTimedOutException
的问题,但旧事务仍然被挂起并保持与数据库的连接(不需要的状态)
有没有办法,如何正确释放损坏的事务(回滚和释放连接)?
EDIT-获取TransactionalStatus的当前代码
public TransactionStatus beginTransaction() {
// transaction begin
logger.debug("Create new transaction.");
TransactionTemplate template = new TransactionTemplate(transactionManager);
template.setTimeout(txConnectionTimeout);
TransactionStatus txStatus = transactionManager.getTransaction(template);
logger.debug(
"Transaction created. TransactionStatus: isCompleted=" + txStatus.isCompleted() + ", isNewTransaction=" +
txStatus.isNewTransaction());
return txStatus;
}