Hibernate, C3P0, Mysql -- Broken Pipe

15

MySQL似乎对连接有8小时的超时限制。我在Tomcat中运行多个WAR,利用Hibernate进行ORM。经过8个小时(即过夜后),当它获取一个空闲连接时,我会遇到断开的管道。

我已经跟踪了代码,并确保提交或回滚所有事务。

这是我的hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
    <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
    <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
    <property name="hibernate.connection.password"></property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <!--property name="hibernate.show_sql">true</property>
    <property name="hibernate.format_sql">true</property-->

    <property name="c3p0.min_size">3</property>
    <property name="c3p0.max_size">5</property>
    <property name="c3p0.timeout">1800</property>
    <property name="c3p0.preferredTestQuery">SELECT 1</property>
    <property name="c3p0.testConnectionOnCheckout">true</property>
    <property name="c3p0.idle_test_period">100</property> <!-- seconds -->

    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <property name="cache.use_query_cache">false</property>
    <property name="cache.use_minimal_puts">false</property>
    <property name="max_fetch_depth">10</property>

    <property name="hibernate.hbm2ddl.auto">update</property>

    <!-- classes removed -->

</session-factory>

我认为可以解决问题的参数是 c3p0.idle_test_period -- 它的默认值是0。但是,即使运行了8个小时,我们仍然遇到了 Broken Pipe 问题。虽然有多篇谷歌索引的帖子,但没有一个能给出令人满意的答案。

5个回答

25

事实证明我错过了一个关键的行,这个行会启用c3p0(我调整的c3p0参数没有效果,因为Hibernate正在使用它内置的连接池——适当地警告不适合生产环境)。在hibernate 2.x中,设置hibernate.c3p0.max_size属性可启用c3p0连接池。但是,在3.x中,您必须指定以下属性--

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

此外,以下是我的最终配置参数--

<property name="hibernate.c3p0.min_size">3</property>
<property name="hibernate.c3p0.max_size">5</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.idle_test_period">100</property> <!-- seconds -->

很不幸的是,Hibernate和c3p0在这方面的文档都非常糟糕。


谢谢,这对我很有帮助。我同意文档的评论。更糟糕的是,c3p0文档建议您为除上述5个之外的所有其他内容使用c3p0.properties,但那并不起作用。只有在没有hibernate前缀的情况下指定persistence.xml时才有效(就像您在原始cfg.xml中所做的那样)。 - Sun
这也帮助了我...我同意关于文档的事情 :). 它们的文档可能需要更加简明扼要。 - Polaris878
如果您使用了CombPooledDataSource的xml配置,则需要设置idleConnectionTestPeriod属性。 - Joseph Lust

2
这里有两个问题。您可以阅读 本文 以获取更多详细信息,但要点如下:
  1. 如果需要,您可以将 MySQL 的 wait_timeout 设置调整为比8小时更长的时间。
  2. Hibernate 设置应在 "c3p0" 前包括 "hibernate.",例如hibernate.c3p0.idle_test_period 而不是只有 c3p0.idle_test_period

今天我会尝试添加Hibernate前缀。我不认为延长MySQL的wait_timeout会有帮助……那只会延迟损坏的管道错误。 - Mark

2
这是一个解决方案,当你的管道断裂,因为Tomcat的wait_timeout=28800秒(8小时)和c3p0中的maxIdleTime=0的组合时:
我通过my.ini文件更改了本地Tomcat的wait_timeout为120秒(2分钟),并放置了以下内容:
maxIdleTime=100
idleConnectionTestPeriod=0(与默认值相同/好像不存在)
其他:
acquireIncrement=2
minPoolSize=2
maxPoolSize=5
maxIdleTimeExcessConnections=10
我没有遇到任何问题。
我不需要使用idleConnectionTestPeriod!
如果Tomcat的wait_timeout为28800秒,并且maxIdleTime为25200,则意味着c3p0将在比Tomcat抛出“broken pipe”异常早3600秒(1小时)关闭空闲连接。这不是吗?
正如您所看到的,我只提供maxIdleTime,没有任何问题。
不幸的是,这些内容:
maxIdleTime
idleConnectionTestPeriod
configuring_connection_testing
testConnectionOnCheckin
对于边角案例并没有太多的解释。
顺便说一下,以下是如何使用Notepad++打开Tomcat的my.ini文件:
http://drupal.org/node/32715#comment-4907440 祝好运, Despot

1
我是一个有用的助手,能够翻译文本。

我遇到了同样的问题,花了一些时间才找到解决方法。

我使用的是Hibernate 4.0.1和mysql 5.1(没有使用Spring框架),我面临着这个问题。首先确保你正确配置了必要的c3p0 jars。

我在hibernate.cfg.xml中使用了以下属性。

<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1;</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.idle_test_period">10</property>
<property name="hibernate.c3p0.acquireRetryAttempts">5</property>
<property name="hibernate.c3p0.acquireRetryDelay">200</property>
<property name="hibernate.c3p0.timeout">40</property>

但这没有用,因为C3p0仍然使用默认属性而不是我在hibernate.cfg.xml中设置的属性,您可以在日志中检查。所以,我在许多网站上搜索正确的解决方案,最终我想出了这个方法。删除cfg.xml中的C3p0属性,在根路径(与cfg.xml一起)中创建c3p0-config.xml,并设置属性如下。

<c3p0-config>
<default-config> 
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">40</property> 
<property name="idleConnectionTestPeriod">10</property> 
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">20</property> 
<property name="minPoolSize">5</property> 
<property name="maxStatements">50</property>
<property name="preferredTestQuery">SELECT 1;</property>
<property name="acquireRetryAttempts">5</property>
<property name="acquireRetryDelay">200</property>
<property name="maxIdleTime">30</property>
</default-config>
</c3p0-config>

但是如果你运行,ORM会使用JDBC连接而不是C3p0连接池,因为我们需要在hibernate.cfg.xml中添加这些属性。

<property name="hibernate.c3p0.validate">true</property>

<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>

现在一切都正常工作(至少对我来说是这样),问题已经解决。

请参考以下内容。

http://www.mchange.com/projects/c3p0/index.html#configuring_connection_testing

https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool

我希望这解决了你的问题。

1
我有几个问题 - - 找不到C3P0ConnectionProvider - 我通过使用Hibernate C3P0版本解决了它。
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.5.6-Final</version>
    </dependency>
          <!-- c3p0 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>3.3.1.GA</version>
    </dependency>

- 我在mysql上遇到了wait_timeout问题。首先我设置了/etc/my.cnf的wait_timeout=10,然后我将空闲超时值更改为小于wait_timeout值的值,即< 10。这解决了我的问题。

    <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" /> <property name="hibernate.c3p0.acquire_increment" value="1" />
        <property name="hibernate.c3p0.idle_test_period"  value="28690"/>
        <property name="hibernate.c3p0.timeout" value="1800" />
        <property name="hibernate.c3p0.max_size" value="5" />
        <property name="hibernate.c3p0.min_size" value="3" />
        <property name="hibernate.c3p0.max_statement" value="50" />
        <property name="hibernate.c3p0.preferredTestQuery" value="select 1;"/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接