我有一个问题,在通过tomcat web应用程序应用户请求重置MySQL数据库后,我会收到tomcat异常。到目前为止,我已尝试将其分解为设置、问题和我的分析,以帮助任何试图阅读本文的人。
重置基本上包括从java代码调用bash脚本以:
这是一个用户启动的过程,通常将数据库恢复到以前的状态,但它也用于从另一个系统导入数据库。一旦一切完成,用户然后尝试访问Web应用的不同部分(即使用相同的会话而不注销/重新登录),该部分执行数据库查询以获取一些数据。
tomcat应用程序查询数据库后,会出现异常:
Dec 29, 2014 3:49:50 PM ERROR BasicSecurityRealm:216 -
ERROR: ----- SQLException -----
Dec 29, 2014 3:49:50 PM INFO BasicSecurityRealm:218 - Exceptioncom.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 234,810 milliseconds ago. The last packet sent successfully to the server was 12 milliseconds ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
...
Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2540)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2990)
即使用户注销并重新登录,我也会看到此异常。如果我刷新页面四次,页面每次都会加载多一点,但会出现一些不同的异常(上面的所有变体-由“EOFEException:Can not read response from server”引起的CommunicationsException)。最后一次,一切似乎都正常运行。
要避免这些异常,我唯一能做的就是重新启动tomcat。我希望避免这种情况,因为这将意味着当前登录的用户将丢失会话,并且必须等待tomcat重新启动才能重新登录。强迫他们注销/重新登录可能是一个可以接受的折衷方案,但这并不能解决问题。
据我所知,我认为问题与JDBC连接池有关。我使用JNDI数据源访问我的数据库,如下所示:
服务器xml:
<GlobalNamingResources>
<Resource name="jdbc/mydb"
auth="Container"
type="javax.sql.DataSource"
maxActive="30" maxIdle="30" maxWait="2147483647"
username="x" password="x"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?autoReconnect=true"/>
web.xml:
<!-- Data source definitions -->
<resource-ref>
<res-ref-name>jdbc/mydb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
爪哇:
// Get connection to specified database
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/mydb");
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery("...");
我认为连接池包含过时/失效的连接。每当我与ds建立连接时。getConnection
,则它将获得这些旧连接中的一个。第一次尝试使用它将失败,连接将被重置(请注意,我使用的是autoReconnect=true
,因此第二次应该(并且确实)起作用)。但是,池中包含许多(在我的例子中,经验上是4或5个)陈旧的连接,因此需要一段时间才能正确重置它们。重置连接后,一切正常。
因为我使用了autoReconnect=true
我可以重新构造我的代码,这样如果我在尝试查询时遇到异常,我就可以重试查询一次。如果它再次失败,那么我就会知道确实存在问题。如果通过,则连接已成功重新建立。
这样做的问题是代码中存在查询EVERYWHERE。重新分解它们需要大量的时间和测试,如果有必要,我会这样做,但希望避免。此外,如果查询因其他原因失败,则在报告之前将尝试两次。对于长查询,这可能会有显著的用户体验延迟,但仅在错误条件下。
另一个解决方案是强制重置/重新连接连接池中的所有连接。我可以通过编程方式(例如,当bash脚本调用完成时,通过我的java代码)或bash脚本(例如,通过某种类型的命令行实用程序)来实现这一点。问题是,我不知道如何做到这一点,或者这是否可能。
我找到了一些关于拦截器的文档,但我不确定这是否适用于重置连接。我会继续调查。
感谢大家的时间和帮助!
该异常将引发由于您的项目包含多个ojdbc
jars(ojdbc6或ojdbc14
)在那一刻你可能会得到异常,当你试图连接oracle12c
删除所有ojdbc
jars在您的项目和添加任何一个jar中,只推荐一个是ojdbc7
jar。
你可以在从游泳池出来之前测试连接
默认情况下Tomcat
在这两种情况下,将下一个属性添加到连接池配置中:
validationQuery=<TEST SQL>
testOnBorrow=true
是否可以配置WebLogic的JDBC连接池,以便在经过一定时间后重置已建立的连接,即使该连接处于活动状态?
问题内容: 我有一个Runnable,它从如下所示的连接池中获得连接,并有60秒的时间对连接进行处理: 当线程在60s之后死掉时,我假定连接已返回到池中,并且当创建新线程时,可以重新使用该连接。但是当我列出我的网络连接时,随着创建更多线程,该列表会不断增长。如上创建的连接是否正确返回到池中,如果可以,我如何强制重新使用连接? 问题答案: 您实际上并没有使用连接池。A 不能直接使用。其目的是作为一个
我在Spring JDBC中使用Spring Boot 1.5.4。 使用Spring JDBC的Spring Boot微服务在尝试执行HTTP PUT时(在一群用户尝试执行HTTP PUT后)会出现以下问题,该问题会逐渐进入Spring JDBC调用: pom.xml: 我猜我需要设置一个JDBC连接池... 在我的application.properties设置中,(我有两个不同的数据库——一
我的Spring Hibernate Web应用程序在MySQL上运行,这给我带来了麻烦。 我四处寻找并尝试了不同的配置,在这个网站上阅读了相当多的帖子,但它仍然会弹出微笑的头像。 错误消息是:由:com.mysql.jdbc.exceptions.jdbc4.通信异常:从服务器成功接收到的最后一个数据包是63,313,144毫秒前。最后一个成功发送到服务器的数据包是63,313,144毫秒前。比
null 任何想法都将受到赞赏。