如何防止 validationQueryTimeout 影响 H2 中的其他 SQL 语句
How to prevent validationQueryTimeout affects other SQL statements in H2
我正在使用以 H2 1.4.199 数据库为后盾的 Dropwizard 1.3.12。
在数据库配置中我有
database:
...
validationQuery: "/* MyService Health Check */ SELECT 1"
validationQueryTimeout: 3s
...
我 运行 遇到的问题是 3 秒的超时也会传播到 Dropwizard 应用程序中完成的真实数据库查询。某些数据库查询被此超时中断。我宁愿让他们多等一会儿。
据我了解validationQueryTimeout
应该只控制validationQuery
的超时。在应用程序内部完成的真实数据库请求不应受此影响。我已经尝试删除 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
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 中获取当前查询超时值,然后再将其设置为验证查询,然后在 运行 验证查询后将其设置回该值。
我正在使用以 H2 1.4.199 数据库为后盾的 Dropwizard 1.3.12。 在数据库配置中我有
database:
...
validationQuery: "/* MyService Health Check */ SELECT 1"
validationQueryTimeout: 3s
...
我 运行 遇到的问题是 3 秒的超时也会传播到 Dropwizard 应用程序中完成的真实数据库查询。某些数据库查询被此超时中断。我宁愿让他们多等一会儿。
据我了解validationQueryTimeout
应该只控制validationQuery
的超时。在应用程序内部完成的真实数据库请求不应受此影响。我已经尝试删除 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
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 中获取当前查询超时值,然后再将其设置为验证查询,然后在 运行 验证查询后将其设置回该值。