Поведение отката при неудачной фиксации из-за отсутствия соединения - PullRequest
0 голосов
/ 15 мая 2018

В настоящее время мы используем HikariCP для управления нашим пулом соединений.

Учитывая приведенный ниже фрагмент кода, мы сталкиваемся со следующей проблемой:

try{
    txn.begin(); 
    entityManager.persist(someEntity);
    txn.commit();// Line 1
} catch(Throwable tx ){
   if(txn.isActive()){
    txn.rollback(); //Line 2
   }
}

EntityManager пытается выполнить коммит длячто ему нужно соединение с HikariCP.Hikari истекает, и, поскольку мы не получили никакого соединения с базой данных, это приводит к исключению.Теперь при попытке отката транзакции последовательность отката пытается снова установить соединение -

  1. Если соединение не найдено, оно снова не удается,
  2. Если соединение найдено изБассейн, он используется.По умолчанию соединение находится в режиме autocommit = true, поэтому откат не выполняется, и пул помечает соединение как разорванное, поскольку ожидаемое состояние соединения при откате - autocommit = 0.

Этостранно, потому что можно предположить, что откат должен происходить на том же соединении, что и при попытке фиксации;если соединение не найдено, откат не должен предприниматься.однако это не то, что происходит.Это приводит к тому, что исправные соединения помечаются как разорванные, и этот цикл повторяется в большинстве 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 Connector: 8.0.11 Eclipselink: 2.5.2 / 2.7 оба пробовали.Двигатель: Innodb.

Редактировать: трассировка стека добавлена ​​по запросу:

08 мая 2018 г. 13: 18: 39,468 - [Thread-159847] - [1161705814: 77] - ПРЕДУПРЕЖДЕНИЕ - Исключение ProxyConnection.checkException (156) - HikariPool-1 - Соединение com.mysql.jdbc.JDBC4Connection@47f8b848 помечено как разорванное из-за SQLSTATE (08003), ErrorCode (0) com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: не удается вызвать откат, когда autocommit = true на солнце.reflect.(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:z3xer.h).pool.ProxyConnection.rollback (ProxyConnection.java:361) на com.zaxxer.hikari.pool.HikariProxyConnection.rollback (HikariProxyConnection.java) на org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicRollback00jj) в org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.rollbackTransaction (DatasourceAccessor.java:688) в org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.rollbackTransaction (DatabaseAccessor.java:1691) в org.ecl.internal.sessions.AbstractSession.basicRollbackTransaction (AbstractSession.java:779) в org.eclipse.persistence.sessions.server.ClientSession.basicRollbackTransaction (ClientSession.java:196) в org.eclipse.persistence.internal.sessions.backTactionaction (AbstractSession.java:3795) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.rollbackTransaction (UnitOfWorkImpl.java:4670)в org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.rollbackTransaction (RepeatableWriteUnitOfWork.java:529) в org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.rollbackatjWW.ReU.sessions.UnitOfWorkImpl.commitToDatabase (UnitOfWorkImpl.java:1480) при org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet (UnitOfWorkImpl.java:1531) в org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork (RepeatableWriteUnitOfWork0com.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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...