9

经过一段时间(几个小时)后,我们收到了 CommunicationsException(来自 DBCP)。错误消息(在异常中)位于此问题的末尾 - 但我没有看到任何配置文件中定义的 wait_timeout 。(我们应该看哪里?tomcat/conf 目录之外的某个地方?)。

其次,正如异常所建议的那样,将“Connector/J 连接属性'autoReconnect = true'”放在哪里?这是tomcat设置中文件conf/context.xml中的资源定义:

<Resource name="jdbc/TomcatResourceName" auth="Container" type="javax.sql.DataSource"
           maxActive="100" maxIdle="30" maxWait="10000"
           removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"
           username="xxxx" password="yyyy"
           driverClassName="com.mysql.jdbc.Driver"
           url="jdbc:mysql://127.0.0.1:3306/dbname?autoReconnect=true"/>

第三,JVM为什么要等到调用executeQuery()才抛出异常?如果连接超时,getConnection 方法应该抛出异常,不是吗?这是我正在谈论的源代码部分:

        try {
                conn = getConnection (true);
                stmt = conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
                                                ResultSet.CONCUR_READ_ONLY);
                rset = stmt.executeQuery (bQuery);
                while (rset.next()) {
                     ....

最后,这是堆栈跟踪的第一几行......

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 84,160,724 milliseconds ago.  The last packet sent successfully to the server was 84,160,848 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1074)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3291)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1938)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2107)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2642)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2571)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1451)
at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208)

这就是我们中的一些人认为“忘记 dbcp,它可能非常依赖于 IDE 配置和幕后魔术,以至于 DriverManager.getConnection(...) 可能更可靠”的原因。对此有何评论?感谢您的见解,-MS

4

2 回答 2

14

由于 DBCP 为即将到来的连接请求保持打开返回的 mysql 连接,它们成为MySQL 服务器超时的受害者。

DBCP 有许多可以提供帮助的特性(可以从 Tomcat 5.5 IIRC 开始使用)。

validationQuery="SELECT 1"
testOnBorrow="true"

验证确保连接在将其返回到执行“借用”方法的 web 应用程序之前是有效的。标志当然启用了此功能。

如果超时(我相信是 8 小时)过去并且连接已失效,则测试一个新连接(如果不再存在,则创建它)并将其提供给 webapp。

其他可能的方法:

  1. testWhileIdle="true"在检测到有效请求之前,在资源设置中使用DBCP 来检查空闲连接。

  2. 使用 'connectionProperties' 来强化你的 MySQL 连接(例如autoReconnect/autoReconnectForPools=true

于 2011-02-09T21:28:47.323 回答
0

DBCP 不适合在生产中使用,甚至作者都这么说(请参阅此演示文稿:http: //www.infoq.com/presentations/Tuning-Tomcat-Mark-Thomas)。

我建议看看 C3P0:http ://www.mchange.com/projects/c3p0/index.html

于 2011-02-09T21:09:15.220 回答