首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止validationQueryTimeout影响H2中的其他SQL语句

如何防止validationQueryTimeout影响H2中的其他SQL语句
EN

Stack Overflow用户
提问于 2019-07-04 19:03:41
回答 1查看 629关注 0票数 1

我使用的是Dropwizard 1.3.12,后端是H2 1.4.199数据库。在我的数据库配置中

代码语言:javascript
复制
database:
  ...
  validationQuery: "/* MyService Health Check */ SELECT 1"
  validationQueryTimeout: 3s
  ...

我遇到的问题是,3s的超时也会传播到在Dropwizard应用程序中完成的实际DB查询。某些数据库查询因此超时而中断。我宁可让他们再等一段时间。

据我所知,validationQueryTimeout应该只控制validationQuery的超时。在应用程序内部完成的实际DB请求不应受此影响。我已经尝试删除validationQueryTimeout,这似乎起到了作用,并删除了查询超时。这样做我认为是最后的解决办法,因为我认为在从连接池获取连接时,在查询上设置超时以验证连接是否已启动并正在运行是有意义的。

我尝试使用Postgresql,validationQueryTimeout似乎不会影响其他数据库查询。

我已经做了一些调试,我想我找到了原因,但我缺乏一个好的解决办法。

执行验证时,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

代码语言:javascript
复制
            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

代码语言:javascript
复制
    /**
     * 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中获取当前查询超时值,然后在运行验证查询之后将其设置回该值。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-10 15:29:17

您说得对,这是已知的H2限制(请参阅herehere)

我猜您可以将超时设置为0,以避免H2的错误行为。然后实现一个在语句执行后检查超时的JdbcInterceptor。但是,当它违反超时时,它不会中止语句,只会在之后报告异常:-(

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56886581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档