使用休眠时数据库连接过多

Posted

技术标签:

【中文标题】使用休眠时数据库连接过多【英文标题】:Too many DB connections while using hibernate 【发布时间】:2012-06-05 08:58:23 【问题描述】:

我是休眠和春季的新手。我们有一个基于 spring 的服务,它使用休眠的 oracle 数据库。此服务部署到 4 个主机。

我们有一个外部 Java 客户端正在使用我们的服务。它每秒进行约 40 次服务调用。所以理想情况下,最多应该有 40(calls)*4(hosts)=160 个打开的连接。但是由于某种原因,我们的服务使用的 DB 连接数增长了 600 多个。

我们可以设置一些指标来检查数据库连接中的泄漏吗?我们如何才能找到这些泄漏连接?

任何帮助将不胜感激。

谢谢, 凯文

【问题讨论】:

【参考方案1】:

如果您在 Hibernate 中使用连接池,那么您的池提供程序可能会保留大量连接,即使它们没有被使用。如果是 c3po,请检查 connection.minPoolSizeconnection.maxPoolSize 属性。

【讨论】:

我在我的配置中设置了最小和最大池大小:跨度> 尝试将 maxPoolSize 设置为 1 一次,看看是否可以解决问题。【参考方案2】:

如果您使用 3rd 方 jars 进行连接轮询,那么您可以启用它们的日志记录并将 logAbandoned 属性设置为 true。所以它会记录你所有的 logAbandoned 连接。

如下图-

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
        <property name="driverClassName" value="$dataSource.driverClassName" />
        <property name="url" value="$dataSource.url" />
        <property name="username" value="$dataSource.username" />
        <property name="password" value="$dataSource.password" />
        <property name="validationQuery" value="$datasource.validationQuery" />
        <property name="maxActive" value="$datasource.maxActive" />
        <property name="maxIdle" value="$datasource.maxIdle" />
        <property name="maxWait" value="$datasource.maxWait" />
        <property name="testOnBorrow" value="true" />
        <property name="testWhileIdle" value="true" />      
        <property name="minIdle" value="$datasource.minIdle" />
        <property name="initialSize" value="$datasource.initialSize" />
        <property name="timeBetweenEvictionRunsMillis" value="$datasource.timeBetweenEvictionRunsMillis" />
        <property name="logAbandoned" value="$datasource.logAbandoned" />
</bean>

【讨论】:

由于我使用的是 c3p0.ComboPooledDataSource,它说 logAbandoned 是无效属性。 我正在使用 Tomcat 池,所以属性就在那里。肯定有一些属性来记录放弃的连接。您将不得不更多地探索 c3p0 属性。【参考方案3】:

我的数据源 bean 如下所示:

<bean id="fssDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass">
         <util:property-path path="FSSConfiguration.driverName"/>
    </property>
    <property name="jdbcUrl">
        <util:property-path path="FSSConfiguration.url" />
    </property>
    <property name="user">
            <util:property-path path="FSSConfiguration.username" />
    </property>
    <property name="password">
            <util:property-path path="FSSConfiguration.password" />
    </property>
    <property name="initialPoolSize" value="1" />
    <property name="minPoolSize" value="1" />
    <property name="maxPoolSize" value="20" />
    <property name="maxIdleTime" value="240" />
    <property name="checkoutTimeout" value="60000" />
    <property name="acquireRetryAttempts" value="0" />
    <property name="acquireRetryDelay" value="1000" />
    <property name="debugUnreturnedConnectionStackTraces" value="true" />
    <property name="unreturnedConnectionTimeout" value="300" />
    <property name="numHelperThreads" value="1" />
    <property name="preferredTestQuery" value="SELECT 1 FROM DUAL" />
</bean>

你能验证一下吗?

【讨论】:

请将其添加到问题中,而不是作为答案【参考方案4】:

您可以在 log4j.xml 中添加以下附加程序,所有 c3p0 日志将被定向到 $catalina.home/logs/c3poLog.log 文件 -

<appender name="c3poLogs" class="org.apache.log4j.DailyRollingFileAppender">
    <param name="Threshold" value="DEBUG"/>
    <param name="Append" value="true"/>
    <param name="File" value="$catalina.home/logs/c3poLog.log"/>
    <!--<param name="DatePattern" value=".yyyy-MM-dd"/>-->
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
    </layout>
</appender>


<category name="com.mchange.v2" additivity="false">
    <priority value="$log4j.category.com.mchange.v2"/>
    <appender-ref ref="c3poLogs"/>
</category>

【讨论】:

以上是关于使用休眠时数据库连接过多的主要内容,如果未能解决你的问题,请参考以下文章

连接过多:Hibernate BoneCP

休眠 - 连接太多

使用 JDBC 获取与 MySQL 的连接时出现“连接过多”

休眠未从 https 域连接

休眠不关闭连接

在休眠中配置时jdbc连接被拒绝