Java 休眠连接泄漏

Java 休眠连接泄漏,java,database,hibernate,rds,Java,Database,Hibernate,Rds,我有一个Java 7 web应用程序堆栈,它使用JBoss 7.1.3和ActiveMQ 5.11.1部署到集群环境中。我使用Hibernate4.0.1将Java应用程序连接到RDS实例 我观察到我们的环境似乎正在泄漏数据库连接。在梳理应用程序时,我们很难确定这些额外的数据库连接可能来自何处。我们的hibernate连接的生命周期相对较短,并且总是在finally{}块中关闭 通过对数据库的查询,我可以看到一个节点在20个连接时保持不变,而另一个节点(主节点)的连接大小将缓慢增长。最终,这个数

我有一个Java 7 web应用程序堆栈,它使用JBoss 7.1.3和ActiveMQ 5.11.1部署到集群环境中。我使用Hibernate4.0.1将Java应用程序连接到RDS实例

我观察到我们的环境似乎正在泄漏数据库连接。在梳理应用程序时,我们很难确定这些额外的数据库连接可能来自何处。我们的hibernate连接的生命周期相对较短,并且总是在finally{}块中关闭

通过对数据库的查询,我可以看到一个节点在20个连接时保持不变,而另一个节点(主节点)的连接大小将缓慢增长。最终,这个数字会增长很多,我们需要在该节点上重新启动应用程序,从而触发另一个节点的故障转移。然后,该节点的连接数将开始增加,而新重新启动的便笺将保持不变为20

我是否可能在Hibernate中遇到任何已知问题?有没有关于如何正确调试的建议

谢谢

更新1

我们使用的连接池定义如下:

<datasource jta="true" jndi-name="java:jboss/datasources/MySqlDS" pool-name="MySqlIDS" enabled="true" use-java-context="true" use-ccm="true">
                    <connection-url>jdbc:mysql://...</connection-url>
                    <driver>com.mysql</driver>
                    <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
                    <pool>
                        <min-pool-size>10</min-pool-size>
                        <max-pool-size>150</max-pool-size>
                        <prefill>true</prefill>
                        <use-strict-min>false</use-strict-min>
                        <flush-strategy>FailingConnectionOnly</flush-strategy>
                    </pool>
                    ...
                </datasource>

无论try块中发生了什么,都可以使用finally块指示在处理结束时希望发生什么。但是如果您在finally块中放置了多个对象,那么如果前面的某个对象抛出异常,那么finally块中的对象就有可能不完整。以下是编写可能导致连接泄漏的JDBC代码的常用方法:

try {
    ...
} finally {
    resultSet.close();
    statement.close();
    connection.close();
}
如果调用close时resultSet或语句抛出异常(例如,由于jdbc对象试图告诉数据库服务器它可以释放为该对象分配的资源,但出现网络故障),则连接不会关闭

您发布的代码的共同点是,在清理过程中有很多事情正在进行,如果其中任何一个出现问题,那么会话就不会关闭

解决方案是限制一个事物引发的异常的范围,以防止调用其他事物,例如通过嵌套finally块:

try {
    try {
        try {
            ...
        } finally {
            try {
                resultSet.close();
            } catch (SQLException e) {
                log.info(e);
            }
        }
    } finally {
        try {
            statement.close();
        } catch (SQLException e) {
            log.info(e);
        }
    }
} finally {
    try {    
        connection.close();
    } catch (SQLException e) {
        log.info(e);
    }
}
因此,如果内部模块出现任何问题,那么外部模块仍然会被调用。这段代码还阻止关闭资源时由于掩盖try块引发的异常而导致的异常(因为try块引发的异常包含有用信息)


(使用try with resources的工作方式基本相同,只是如果try块正常完成,并且任何资源抛出了一些东西,那么关闭时抛出的异常不会被抑制。)

您使用的是连接池吗?可能是Hibernate造成的。然而,要归咎于代码的可能性要高出1000倍。阅读连接池上的文档,它可能会跟踪签出时间过长的连接。@ChrisThompson问得好,很抱歉没有包括这些信息。是的,我们使用的是游泳池(最小尺寸为10,最大尺寸为150)。但是我们的应用程序似乎超过了150(如果我们允许的话),我们开始出现JDBC异常。@Kayaman我同意,我更愿意指责我的东西。我不知道如何追踪我们的泄密来源。我已将所有Hibertnate内容集中到一个实用程序类中,该类用于管理新会话、事务计数、清理等。当我们逐步浏览代码时,我们找不到任何泄漏,但我想知道是否是真实环境中的并发性导致了泄漏。@Trialum:eww。如果清理所做的任何操作引发异常,则跳过关闭。您如何进行清理需要重新评估。
try {
    try {
        try {
            ...
        } finally {
            try {
                resultSet.close();
            } catch (SQLException e) {
                log.info(e);
            }
        }
    } finally {
        try {
            statement.close();
        } catch (SQLException e) {
            log.info(e);
        }
    }
} finally {
    try {    
        connection.close();
    } catch (SQLException e) {
        log.info(e);
    }
}