目前,我们正在使用HikariCP来管理我们的连接池。
鉴于下面提到的代码段,我们面临以下问题:
try{
txn.begin();
entityManager.persist(someEntity);
txn.commit();// Line 1
} catch(Throwable tx ){
if(txn.isActive()){
txn.rollback(); //Line 2
}
}
EntityManager尝试提交,因为它需要来自HikariCP的连接。 Hikari超时,因为我们没有得到任何数据库连接,这导致异常。现在,当尝试回滚事务时,回滚序列会尝试再次建立连接 -
这很奇怪,因为人们会认为回滚应该在尝试提交的同一连接上发生;如果未找到连接,则不应尝试回滚。然而,这不是正在发生的事情。这会导致健康的连接被标记为已损坏,并且只要池上有压力,此循环就会在大多数API中重复。
我们正在使用EclipseLink版本2.5.2,但即使在最新版本中也存在此问题。我可以将它追溯到DatasourceAccessor.java中的回滚序列的这一部分:
public synchronized void incrementCallCount(AbstractSession session) {
this.callCount++;
if (this.callCount == 1) {
// If the login is null, then this accessor has never been connected.
if (this.login == null) {
throw DatabaseException.databaseAccessorNotConnected();
}
// If the connection is no longer connected, it may have timed out.
if (this.datasourceConnection != null) {
if (shouldCheckConnection && !isConnected()) {
if (this.isInTransaction) {
throw DatabaseException.databaseAccessorNotConnected();
} else {
reconnect(session);
}
}
} else {
// If ExternalConnectionPooling is used, the connection can be re-established.
if (this.usesExternalConnectionPooling) {
reconnect(session); //Why reconnect?
session.postAcquireConnection(this);
currentSession = session;
} else {
throw DatabaseException.databaseAccessorNotConnected();
}
}
}
}
恕我直言,在进行回滚时,不应获取新连接。这没有道理。我错过了什么吗?
Java:1.8.0_91 Hikari:3.0.1 MySQL连接器:8.0.11 Eclipselink:2.5.2 / 2.7都尝试过。 发动机:Innodb。
编辑:按要求添加Stacktrace:
2018年5月8日13:18:39,468 - [Thread-159847] - [1161705814:77] - WARN - ProxyConnection.checkException(156) - HikariPool-1 - 连接com.mysql.jdbc.JDBC4Connection@47f8b848标记为 由于SQLSTATE(08003)而被破坏,ErrorCode(0) com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:当autocommit = true时无法调用回滚 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在com.mysql.jdbc.Util.handleNewInstance(Util.java:408) 在com.mysql.jdbc.Util.getInstance(Util.java:383) 在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1023) 在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:997) 在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:983) 在com.mysql.jdbc.SQLError.createSQLException(SQLError.java:928) 在com.mysql.jdbc.ConnectionImpl.rollback(ConnectionImpl.java:5078) 在com.zaxxer.hikari.pool.ProxyConnection.rollback(ProxyConnection.java:361) 在com.zaxxer.hikari.pool.HikariProxyConnection.rollback(HikariProxyConnection.java) at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicRollbackTransaction(DatabaseAccessor.java:1700) at org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.rollbackTransaction(DatasourceAccessor.java:688) 在org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.rollbackTransaction(DatabaseAccessor.java:1691) at org.eclipse.persistence.internal.sessions.AbstractSession.basicRollbackTransaction(AbstractSession.java:779) 在org.eclipse.persistence.sessions.server.ClientSession.basicRollbackTransaction(ClientSession.java:196) at org.eclipse.persistence.internal.sessions.AbstractSession.rollbackTransaction(AbstractSession.java:3795) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.rollbackTransaction(UnitOfWorkImpl.java:4670) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.rollbackTransaction(RepeatableWriteUnitOfWork.java:529) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.rollbackTransaction(RepeatableWriteUnitOfWork.java:545) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1480) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132) 在com.paytm.wallet.dao.domain.UserBeneficiaryManager.updateBenefeciaryDetails(UserBeneficiaryManager.java:81) 在com.paytm.wallet.web.wrapper.business.impl.UserBeneficiaryHelper.addBeneficary(UserBeneficiaryHelper.java:247) 在com.paytm.wallet.web.concurrent.AddBeneficiaryThread.run(AddBeneficiaryThread.java:36) 在java.lang.Thread.run(Thread.java:745)