java - 从 Tomcat 中的池中中止/清除无效的数据库连接

标签 java sql oracle connection tomcat7

数据库中断后,Tomcat 中的连接池出现问题。

这个心跳服务 servlet 在数据库中断后不会恢复。

我已经尝试过 standard answer以及其他,具体来说:

  1. 添加到 server.xml 中的资源部分

    validationQuery="select 1 from dual"
    testOnBorrow="true"
    removeAbandoned="true"
    removeAbandonedTimeout="120"
    logAbandoned="true"
    
  2. 尝试关闭连接并检查有效性:

    if (connection != null && !connection.isValid(10)) {
        connection.close();
    }
    

    (导致java.sql.SQLException:连接已关闭)

  3. 尝试中止连接(不确定是否正确)

    if (connection != null && !connection.isValid(10)) {
        connection.abort();
    }
    

    (导致java.lang.NoSuchMethodError:java.sql.Connection.abort(Ljava/util/concurrent/Executor;)V)

尝试 2) 和 3) 显示连接确实无效,并且它知道这一点。问题是 - 如何摧毁它?

Tomcat版本:7.0.29

最佳答案

由于“testOnBorrow=true”设置,池将为您销毁无效连接(请注意,“放弃”设置仅适用于未返回池的连接)。 所以事情应该是这样的:

  • servlet 借用连接、执行查询并将连接返回到池中。
  • servlet 借用连接,数据库崩溃,servlet 收到各种可怕的 SQL 错误,但仍然将连接返回到池
  • 数据库已重新启动
  • 在下一次心跳时,servlet 会借用连接。 Tomcat 的池将“测试借用”,发现旧连接已损坏,删除(并关闭)连接,尝试另一个连接,发现它也已损坏,等等,然后池决定创建一个新连接,测试它正常并将其移交给 servlet。
  • servlet 接收新的有效连接,执行查询并将连接返回到池中。

我不确定当“借用测试”表明连接已损坏时 Tomcat 池的行为如何 (1):它可能不会立即创建新连接,或者在无法从池中获取有效连接时抛出错误。但我希望池能够有效地刷新自身并重新填充新的(有效)连接。

(1) 也就是说,如果“借用测试”确实完成了,则this post表明情况并非如此...

<小时/>

如果池没有自行刷新,您可以在发现连接无效后尝试以编程方式执行此操作。我以前没有尝试过这个,希望你能让它发挥作用。描述了以下方法here :
进入 JNDI 上下文,拉出 DataSource 对象,祈祷,将其转换到 org.apache.tomcat.jdbc.pool。 DataSource ,然后调用 purge() 方法。
或者,使用JMX并调用purge通过 MBean 的方法。

如果您在数据库崩溃后遇到线程挂起的情况,您可能必须采用 this 中描述的解决方法。回答。

关于java - 从 Tomcat 中的池中中止/清除无效的数据库连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21166584/

相关文章:

sql - 对可以具有不同属性的实体建模的最佳方法是什么?

sql - Oracle 数字字符串列和索引

oracle - 如何在oracle sql developer中运行存储过程?

sql - 有条件地选择一列

java - 使用 TLS 连接到 MariaDB 的 Tomcat 抛出 javax.naming.NamingException;命令行连接正常工作

Java使用RSA从模数和指数生成 key 进行加密/解密

java - 如何实现一个AlertDialog.Builder 选中项的点击事件?

java - 如何解决 "org.hibernate.QueryException: Not all named parameters have been set"错误?

c# - 转换 SqlDataReaders

SQL 使用 OBJECT 作为 ORDER 方法的参数