Как предотвратить validationQueryTimeout влияет на другие операторы SQL в H2 - PullRequest
1 голос
/ 04 июля 2019

Я использую Dropwizard 1.3.12 с базой данных H2 1.4.199.В конфигурации базы данных у меня есть

database:
  ...
  validationQuery: "/* MyService Health Check */ SELECT 1"
  validationQueryTimeout: 3s
  ...

Проблема, с которой я сталкиваюсь, состоит в том, что тайм-аут 3 с также распространяется на реальные запросы к БД, выполненные в приложении Dropwizard.Некоторые запросы к БД прерываются этим тайм-аутом.Я бы предпочел, чтобы они подождали немного дольше.

Насколько я понимаю, validationQueryTimeout должен контролировать только время ожидания validationQuery.Это не должно влиять на реальные запросы к БД, выполняемые внутри приложения.Я попытался удалить validationQueryTimeout, и это, кажется, делает трюк и удаляет таймаут запроса.Делая это, я рассматриваю это как крайнее решение, поскольку думаю, что имеет смысл установить таймаут для запроса, который проверяет, что соединение установлено и работает при извлечении соединения из пула соединений.

Я пытался использовать Postgresqlи validationQueryTimeout, похоже, не влияет на другие запросы к БД.

Я провел некоторую отладку и думаю, что нашел причину, но мне не хватает хорошего обходного пути.

При выполненииvalidation tomcat-jdbc устанавливает время ожидания запроса в операторе проверки.https://github.com/apache/tomcat/blob/9.0.16/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java#L536-L544

            stmt = connection.createStatement();

            int validationQueryTimeout = poolProperties.getValidationQueryTimeout();
            if (validationQueryTimeout > 0) {
                stmt.setQueryTimeout(validationQueryTimeout);
            }

            stmt.execute(query);
            stmt.close();

Большая проблема заключается в том, что H2 сохраняет время ожидания на уровне соединения, а не на уровне операторов.https://github.com/h2database/h2database/blob/version-1.4.199/h2/src/main/org/h2/jdbc/JdbcStatement.java#L695-L717

    /**
     * Sets the current query timeout in seconds.
     * Changing the value will affect all statements of this connection.
     * This method does not commit a transaction,
     * and rolling back a transaction does not affect this setting.
     *
     * @param seconds the timeout in seconds - 0 means no timeout, values
     *        smaller 0 will throw an exception
     * @throws SQLException if this object is closed
     */
    @Override
    public void setQueryTimeout(int seconds) throws SQLException {
        try {
            debugCodeCall("setQueryTimeout", seconds);
            checkClosed();
            if (seconds < 0) {
                throw DbException.getInvalidValueException("seconds", seconds);
            }
            conn.setQueryTimeout(seconds);
        } catch (Exception e) {
            throw logAndConvert(e);
        }
    }

Могу ли я что-нибудь сделать?Или требуется исправление в h2 или tomcat-jdbc?Я могу подумать о том, чтобы получить текущее значение тайм-аута запроса в tomcat-jdbc, прежде чем устанавливать его для запроса проверки, а затем вернуть его к этому значению после выполнения запроса проверки.

1 Ответ

1 голос
/ 10 июля 2019

Вы правы, это известное ограничение H2 (см. здесь и здесь )

Я думаю, вы могли бы установить таймаут на 0, чтобы избежатьнеправильное поведение H2.Затем реализуйте JdbcInterceptor, который проверяет время ожидания после выполнения оператора.Тем не менее, он не прервет оператор, когда он превысит тайм-аут, будет сообщать только после исключения :-(

...