数据库中断后,Tomcat 中的连接池出现问题。
这个心跳服务 servlet 在数据库中断后不会恢复。
我已经尝试过 standard answer以及其他,具体来说:
添加到 server.xml 中的资源部分
validationQuery="select 1 from dual" testOnBorrow="true" removeAbandoned="true" removeAbandonedTimeout="120" logAbandoned="true"
尝试关闭连接并检查有效性:
if (connection != null && !connection.isValid(10)) { connection.close(); }
(导致
java.sql.SQLException:连接已关闭
)尝试
中止
连接(不确定是否正确)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/