【问题标题】:WebApp (Tomcat-jdbc) Pooled DB connection throwing abandon exceptionWebApp(Tomcat-jdbc)池化数据库连接抛出放弃异常
【发布时间】:2012-10-19 04:57:45
【问题描述】:

我已经浏览了一段时间,并且在此过程中咬牙切齿,但找不到与我的问题完全匹配的问题。
简而言之,在 60 秒不活动后,我得到了极好的堆栈跟踪(org.apache.tomcat.jdbc.pool.ConnectionPool 放弃),这是几个服务器端线程的正常行为。
我直接使用 Tomcat JDBC 连接池 (org.apache.tomcat.jdbc.pool.DataSource)
堆栈跟踪:

2012 年 10 月 29 日 8:55:50 PM org.apache.tomcat.jdbc.pool.ConnectionPool 放弃 警告:连接已被放弃 PooledConnection[com.mysql.jdbc.JDBC4Connection@1ad2916]:java.lang.Exception 在 org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:967) 在 org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:721) 在 org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:579) 在 org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174) 在 org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:111) 在 com.getsom.getConnection(DAO.java:1444) 在 com.getsom.PreparedConnection.(PreparedConnection.java:48) 在 com.getsom.Alarms.run(Alarms.java:492)

我的 PoolProperties 配置如下:

    PoolProperties pp = new PoolProperties();

    pp.setUrl( someValidUrl);
    pp.setDriverClassName("com.mysql.jdbc.Driver");
    pp.setUsername( someUser);
    pp.setPassword( somePassword);
    pp.setJmxEnabled( true);
    pp.setTestWhileIdle( true);
    pp.setTestOnBorrow( true);
    pp.setValidationQuery( "SELECT 1");
    pp.setTestOnReturn( false);
    pp.setValidationInterval(30000);
    pp.setTimeBetweenEvictionRunsMillis(30000);
    pp.setMaxActive(100);
    pp.setInitialSize(10);
    pp.setMaxWait(10000);
    pp.setMinEvictableIdleTimeMillis(30000);
    pp.setMinIdle(10);

    pp.setLogAbandoned(true);
    pp.setRemoveAbandoned(true);
    pp.setRemoveAbandonedTimeout(60);
    pp.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");    

    setPoolProperties(pp);

我希望 setValidationInterval(30000) 能救我,因为 30 秒在连接生命周期中并不多。无论如何,问题是:
为了让这种联系永远存在,我缺少什么?
很高兴知道:为什么我在声明连接的函数中超时,尽管它在 30 秒前被调用。

【问题讨论】:

    标签: java mysql tomcat connection-pooling


    【解决方案1】:

    即使我迟到了 1 年多才访问此页面,但我在这里偶然发现,因为我遇到了类似的问题并且也需要解决方案。所以我想我会分享最终对我有用的东西。

    就我而言,在找到并阅读了这篇文章后 >>> configuring-jdbc-pool-high-concurrency - 我刚刚在我的池配置中添加了一个这样的拦截器;

    "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
    

    因此,您执行setJdbcInterceptors(...) 的行(来自您上面发布的代码)现在应该如下所示;

    p.setJdbcInterceptors(
                "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
                + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
                + "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
    

    解释 - 引用文章,它说;

    我们要确保当我们检测到连接仍在使用时,我们重置超时计时器,这样连接就不会被视为放弃。我们通过插入一个拦截器来做到这一点。

    每次准备语句或执行查询时,计时器都会重置连接池上的放弃计时器。这样……进行大量查询和更新,不会超时。

    请记住,您很可能很久以前就已经解决了这个问题,我仍然希望这可以帮助其他遇到类似问题的人,就像我一样。

    干杯!

    【讨论】:

    • 这个答案也是我的解决方案!谢谢你们!
    【解决方案2】:

    我可以看到这个帖子很旧,但是我遇到了类似的问题,最终我找到了导致它的原因,所以如果它可以帮助某人,我想分享一下:

    我使用了来自 RESTful Web 服务的连接。在服务端处理来自客户端的请求的界面中,我不小心在方法签名中放入了'throws IOException':

    @GET
    @Path("/databases")
    @Produces(MediaType.APPLICATION_JSON)
    public String getAllDatabases() throws IOException {
    

    【讨论】:

      【解决方案3】:

      有一个类似的问题,即tomcat正在关闭JDBC连接,因为它因为事务需要很长时间而被放弃。

      通过意识到abandonedidle 是不同的并通过设置:spring.datasource.tomcat.removeAbandonedTimeout: 86400 #seconds 来解决它

      【讨论】:

        【解决方案4】:

        只需在tomcat7 conf/server.xml 或context.xml 中添加以下条目即可,只要您的资源标签存在即可。

        jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
        org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;
        org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
        

        【讨论】:

          【解决方案5】:

          这个问题的答案对我很有帮助。

          虽然就我而言,我已经配置了“ResetAbandonedTimer”JDBC 拦截器。

          但是,我的查询运行时间超过了我也配置的“removeAbandonedTimeout”。一旦我增加了“removeAbandonedTimeout”,问题就消失了。

          【讨论】:

            【解决方案6】:

            如果您在 tomcat 的 context.xml 中定义数据源,则应添加 ResetAbandonedTimer,如下所示:

            jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer"
            

            设置 ResetAbandonedTimer 后,问题在我的应用程序中得到解决,请求您让我知道 ResetAbandonedTimer 拦截器和 removeAbandoned="true" removeAbandonedTimeout="60" 之间是否有任何关系

            【讨论】:

              【解决方案7】:

              在配置文件中跟踪“removeAbandonedTimeout”。这应该是应用程序中的最大运行查询。否则它将在执行过程中关闭连接

              【讨论】:

              • 我有同样的问题,并且已经设置了 removeAbandonedTimeout ,但它没有帮助,不幸的是。
              • 您能解释一下如何在 Tomcat 中“跟踪”该资源属性吗?
              • 警告:这只有在如果您只对连接执行一次查询然后再次关闭它,或者使用 ResetAbandonedTimer 过滤器时才成立。否则批处理操作可能会超时运行。
              【解决方案8】:

              您是否在 Tomcat 网站上看到过与PoolConnection 相关的信息。或许你需要看一下minEvictableIdleTimeMillis的属性@

              要回答您的问题,您正在超时,因为您每 30 秒检查一次空闲和放弃连接(请参阅TimeBetweenEvictionRunsMillis),并且由于您将可撤销的空闲超时设置为 30 秒(请参阅minEvictableIdleTimeMillis),然后您结束和你所拥有的一样。您说过您在空闲时收到此异常,我怀疑该异常是关闭空闲连接而不是放弃连接的结果。据我了解,放弃连接用于超时时间超过预期的查询(而不是空闲连接)。

              就我个人而言,我不希望连接永远处于活动状态,因为它们会不必要地消耗资源(即与数据库的连接)。我会玩弄我的最大连接数、驱逐运行和空闲时间来优化我自己的需求。我想你可以将这些值设置得足够大,几乎永远存在!这确实取决于你在做什么......

              很抱歉,我无法提供更多帮助。

              【讨论】:

              • 是的,我已经广泛阅读了这篇文章。我相信这与放弃有关,而不是驱逐。我的假设是 ConnectionPool 会让这些连接保持活跃。
              • 您在执行查询时是否收到错误消息?您的查询运行时间超过 60 秒似乎很奇怪!
              • 不。有问题的线程是空闲的。由于 ConnectionPool 假定连接被放弃,这是问题所在。
              • 如果您遇到“已放弃”而不是“空闲”连接的问题,请尝试设置(为我解决了问题):spring.datasource.tomcat.removeAbandonedTimeout: 86400 #seconds
              猜你喜欢
              • 2013-05-09
              • 1970-01-01
              • 2013-05-01
              • 2014-06-30
              • 2014-12-20
              • 2012-11-04
              • 1970-01-01
              • 2012-03-02
              • 1970-01-01
              相关资源
              最近更新 更多