【发布时间】:2020-01-19 20:00:05
【问题描述】:
我正在开发一个涉及多个数据源的微服务。为了简单起见,我在这里使用了两个数据源,MySql 和 Oracle。这是伪代码。
domain.withNewTransaction {
mySql.executeUpdate("update mySqlTable")
oracle.executeUpdate("update oracleTable")
}
有一天尝试提交oracle更新时抛出异常,但是我发现mysql更新已成功提交并且没有回滚。 我发现框架使用 ChainedTransactionManager.java 来管理多个数据源提交。这是提交方法的代码。
public void commit(TransactionStatus status) throws TransactionException {
MultiTransactionStatus multiTransactionStatus = (MultiTransactionStatus) status;
boolean commit = true;
Exception commitException = null;
PlatformTransactionManager commitExceptionTransactionManager = null;
for (PlatformTransactionManager transactionManager : reverse(transactionManagers)) {
if (commit) {
try {
multiTransactionStatus.commit(transactionManager);
} catch (Exception ex) {
commit = false;
commitException = ex;
commitExceptionTransactionManager = transactionManager;
}
} else {
// after unsucessfull commit we must try to rollback remaining transaction managers
try {
multiTransactionStatus.rollback(transactionManager);
} catch (Exception ex) {
LOGGER.warn("Rollback exception (after commit) (" + transactionManager + ") " + ex.getMessage(), ex);
}
}
}
if (multiTransactionStatus.isNewSynchonization()) {
synchronizationManager.clearSynchronization();
}
if (commitException != null) {
boolean firstTransactionManagerFailed = commitExceptionTransactionManager == getLastTransactionManager();
int transactionState = firstTransactionManagerFailed ? HeuristicCompletionException.STATE_ROLLED_BACK
: HeuristicCompletionException.STATE_MIXED;
throw new HeuristicCompletionException(transactionState, commitException);
}
}
事实证明,当一个数据源提交失败时,ChainedTransactionManager 只会回滚剩余的未提交的,与已提交的事务无关。
我了解回滚已提交的事务是复杂且有风险的。我想知道应用程序开发人员是否有更好的想法来处理这个多数据源事务提交失败。提前致谢!
【问题讨论】:
标签: java database spring transactions