【问题标题】:Too many pool exhaustion errors with jdbc-pooljdbc-pool 的池耗尽错误太多
【发布时间】:2013-03-26 21:52:23
【问题描述】:

我有一个应用在上个月开始使用jdbc-pool 进行 MySQL 连接处理。在此之前,我一直在使用 Apache 的commons-dbcp。在阅读了一些显示它更快、维护得更好等的分析后,我切换到 jdbc-pool。但是,我开始注意到 很多 更多的用户看到池耗尽错误。

我不知道这是否与从 commons 切换到 jdbc-pool 有关,但它似乎从那个时候开始,我正在考虑构建我们的产品以恢复并将其提供给有 db 错误的人看看它有什么影响。

我编写了一个文档,通过调整池连接、增加最大等待等来帮助他们进行故障排除。但是,我开始看到很多人报告池耗尽错误,即使他们的应用程序基本上处于空闲状态。 show full processlist 似乎显示 19 个连接处于“睡眠”状态,其中 1 个连接处于活动状态。

我在生产环境和开发环境中都经常运行该应用程序,但从未遇到过问题。我更擅长管理我的 mysql 环境,但池系统较弱的竞争对手产品没有此类问题。

我花了很多时间阅读 jdbc 和 pooling 文档,但是 我是否在做一些会导致性能不佳的事情

这些是我们使用默认值的数据库连接代码示例。

// Called once on application start, connects to the database
public DataSource initDbPool(){
    String dns = "jdbc:mysql://"+config.getString("prism.mysql.hostname")+":"+config.getString("prism.mysql.port")+"/"+config.getString("prism.mysql.database");
    pool = new DataSource();
    pool.setDriverClassName("com.mysql.jdbc.Driver");
    pool.setUrl(dns);
    pool.setUsername( /*username*/ );
    pool.setPassword( /*password*/ );
    pool.setInitialSize( 10 );
    pool.setMaxActive( 20 );
    pool.setMaxIdle( 10 );
    pool.setMaxWait( 30000 );
    pool.setRemoveAbandoned(true);
    pool.setRemoveAbandonedTimeout(60);
    return pool;
}

// Called from various classes that need to run queries
public static Connection dbc(){
    Connection con = null;
    try {
        con = pool.getConnection();
    } catch (SQLException e) {
        System.out.print("Database connection failed. " + e.getMessage());
        e.printStackTrace();
    }
    return con;
}

The actual code can be seen here.

我也从不喜欢查询。我们一直在运行批量插入查询,但我们已经使用队列系统和批量插入对其进行了优化,因此它非常快并且使用尽可能少的开销。

【问题讨论】:

    标签: java jdbc


    【解决方案1】:

    我看到你有close() 但不在finally 块中。这意味着如果发生异常,连接将丢失。我怀疑commons-dhcp 处理泄漏连接的方式与jdbc-pool 不同。

    removeAbandoned 配置选项,默认为off,因为它是Right Thing™。但据我了解,它不提供任何保证,因为它会通过超时关闭它们。如果您在短时间内有很多异常,它可能会耗尽池。因此,更好的方法是始终关闭 finally 块中的所有连接。

    【讨论】:

    • 所以你的意思是这样的:pste.me/TmcFT?关闭本身需要尝试/捕获,但我认为我可以忽略它?还是您建议我在关闭连接的所有地方都使用 finally?还是建议我完全关闭池连接,然后尝试重新连接?
    • 澄清一下,很可能在短时间内出现很多异常。我们的应用程序不断记录数据,如果有什么东西触发了池耗尽错误,它们似乎总是开始堆积,应用程序挂起/崩溃。
    • 我已经浏览了我的代码,现在完全看到了这个问题。如果引发异常,它可能不会关闭连接,这可能会导致泄漏,所以我将所有内容都移到了 finally 块中,并让一些用户尝试。
    • @BotskoNet 是的,通常你应该这样做...finally{try{con.close()}catch(Exception e){log.error(e);}}。或者使用 java 7 try-with-resources 块。从池中关闭连接意味着将物理连接返回到池中。
    猜你喜欢
    • 2012-11-04
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 2014-12-26
    相关资源
    最近更新 更多