org.apache.tomcat.jdbc.pool 中的验证查询

Posted

技术标签:

【中文标题】org.apache.tomcat.jdbc.pool 中的验证查询【英文标题】:Validation Query in org.apache.tomcat.jdbc.pool 【发布时间】:2011-08-22 22:01:54 【问题描述】:

我最近正在使用新的 Tomcat JDBC 连接池(org.apache.tomcat.jdbc.pool,版本 7.0.20)进行一些测试。我对使用验证查询的理解是,例如,当我重新启动数据库并且池会丢失所有连接,它会自动尝试恢复它们。

这里是初始化代码:

...

PoolProperties p = new PoolProperties();
p.setUrl(connString);
p.setDriverClassName("org.postgresql.Driver");
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT version();");
p.setTestOnReturn(false);
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(maximumDbConnections);
p.setInitialSize(1);
p.setMaxWait(10000);
p.setRemoveAbandonedTimeout(60);
p.setMinEvictableIdleTimeMillis(30000);
p.setMinIdle(minimumIdleDbConnections);
p.setMaxIdle(maximumIdleDbConnections);
p.setLogAbandoned(true);
p.setRemoveAbandoned(true);
p.setInitSQL("SET application_name = 'My Server'");
datasource = new DataSource();
datasource.setPoolProperties(p);

...

然后我启动一个计时器,每次它触发时,我都会从池中获取连接:

...

Connection conn = App.datasource.getConnection();

...

当我启动数据库时,它并没有像预期的那样尝试恢复连接,我总是收到以下异常:

[2011-08-22 23:50:53,066][871009][ERROR]DbPollThread - 1  [0144] SQLException while checking for hangig jobs
java.sql.SQLException: Connection has already been closed.
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:118)
    at $Proxy2.prepareStatement(Unknown Source)
    at org.voxtelo.faxserver.internal.database.FaxDatabaseHandler.resetOrDeactivateHangingJobs(FaxDatabaseHandler.java:404)
    at org.voxtelo.faxserver.internal.database.FaxDatabaseHandler.pollJobsFromDB(FaxDatabaseHandler.java:884)
    at org.voxtelo.faxserver.internal.database.FaxDatabaseHandler.access$1(FaxDatabaseHandler.java:882)
    at org.voxtelo.faxserver.internal.database.FaxDatabaseHandler$PollDatabaseTask.run(FaxDatabaseHandler.java:940)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)

【问题讨论】:

【参考方案1】:

最后我自己发现了这个问题。代码

conn = App.datasource.getConnection();

当异常被抛出时,我得到的连接不再到达。所以所有的操作仍然在旧的、断开的连接上完成。现在我确保 conn = App.datasource.getConnection();总是在 db 操作之前调用,一切都按预期工作。

【讨论】:

【参考方案2】:

注意setValidationInterval(30000),因为这意味着验证查询将每 30 秒完成一次。我认为将其设置为 0 以在每次请求连接时触发验证查询会更安全。

【讨论】:

-1,这是不正确的。他只将“testOnBorrow”设置为 true,因此这意味着验证查询仅在请求连接时运行。

以上是关于org.apache.tomcat.jdbc.pool 中的验证查询的主要内容,如果未能解决你的问题,请参考以下文章