15

MySQL seems to have an 8 hour time out on its connections. I'm running multiple WARs in Tomcat utilizing Hibernate for ORM. After 8 hours (i.e. overnight), I get broken pipes when it picks up an idle connection.

I've already traced through the code and made doubly sure I commit or rollback all transactions.

Here is my 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>

The parameter I thought would have fixed it was the c3p0.idle_test_period -- It defaults to 0. However, we still have the Broken Pipe issue after 8 hours of running. While there are multiple posts index via Google, none arrive at a satisfactory answer.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Mark
  • 4,446
  • 5
  • 26
  • 34

5 Answers5

25

So it turns out I was missing a key line that enabled c3p0 (the c3p0 parameters I was tweaking were having no effect because Hibernate was using it's built in connection pool -- which it appropriately warns is not suitable for production). In hibernate 2.x, setting the hibernate.c3p0.max_size property enabled c3p0 connection pooling. However, in 3.x you must specify the following property --

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

Additionally, here are my final configuration parameters --

<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 -->

It's rather unfortunate that both Hibernate and c3p0 have abysmal documentation in this regard.

Mark
  • 4,446
  • 5
  • 26
  • 34
  • Thank you, this helped me. I agree with the documentation comment. Even worse, c3p0 documentation advises you to use c3p0.properties for all others except the above 5, but that does not work. It only works when you specify in the persistence.xml without the hibernate prefix (as you have done in your original cfg.xml) – Sun Jul 16 '10 at 15:58
  • This helped me also... I agree about the documentation thing :). It could be a little more straightforward in their documentation. – DigitalZebra Aug 03 '10 at 04:42
  • If you used the xml config for CombPooledDataSource the property is `idleConnectionTestPeriod` that you need to have. – Joseph Lust Mar 07 '13 at 11:23
2

This is a solution when you have a broken pipe because of combination of tomcat's wait_timeout=28800 sec(8h) and maxIdleTime=0 in c3p0:

I've changed the local tomcat wait_timeout via my.ini file to 120sec (2 min). And I placed the following:
maxIdleTime=100
idleConnectionTestPeriod=0 (same as default/as if it didn't exist)
other:
acquireIncrement=2
minPoolSize=2
maxPoolSize=5
maxIdleTimeExcessConnections=10

I had no problems with this setup.

I didn't need to use idleConnectionTestPeriod!

If tomcat's wait_timeout is 28800 sec, and maxIdleTime is 25200, it means that c3p0 will close the idle connection in 3600sec (1h) earlier, before tomcat throws a "broken pipe" exception. Isn't that right?!

As you can see I have no issues with providing only maxIdleTime.

Unfortunately, these:
maxIdleTime
idleConnectionTestPeriod
configuring_connection_testing
testConnectionOnCheckin
don't explain too much the corner cases.

And, btw, here is how to open the tomcat's my.ini file with Notepad++: http://drupal.org/node/32715#comment-4907440

Cheers,
Despot

despot
  • 7,167
  • 9
  • 44
  • 63
2

There are two things going on here. You should read this article for more details, but the take-aways are:

  1. You can adjust the MySQL wait_timeout setting to something larger than 8 hours, if desired.
  2. The Hibernate settings should include "hibernate." before the "c3p0", e.g. hibernate.c3p0.idle_test_period instead of just c3p0.idle_test_period
Matt Solnit
  • 32,152
  • 8
  • 53
  • 57
  • I'll try the adding the hibernate prefix today. I don't think extending the MySQL wait_timeout would help... I would just delay the broken pipe error. – Mark Apr 10 '09 at 14:11
1

I've several problem - - C3P0ConnectionProvider was not found - I solve it by using the hibernate c3p0 version

        <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>

- I have that wait_timeout issue on mysql. First I set /etc/my.cnf wait_timeout=10 then I changed the Idle time out value to lower than the wait_timeout value which < 10 That solved my problem.

    <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;"/>
Imtiaz Mirza
  • 591
  • 1
  • 7
  • 26
1

I was getting the same problem and it took time to figure out the solution.

I use Hibernate 4.0.1 and mysql 5.1(no spring framework) and I was facing the issue. First make sure that you configured the c3p0 jars properly which are essential.

I used these properties in 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>

But it's of no use 'cause C3p0 was still taking the default properties not the properties which I set in hibernate.cfg.xml, You can check it in logs. So, I searched many websites for right solution and finally I came up with this. remove the C3p0 properties in cfg.xml and create c3p0-config.xml in the root path(along with cfg.xml) and set properties as follows.

<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>

but if you run, ORM takes the jdbc connection but not C3p0 connection pool 'cause we should add these properties in hibernate.cfg.xml

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

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

now everything works fine(At least it worked fine for me) and the issue is solved.

check the following for references.

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

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

I hope this solves your problem.

chaitanya89
  • 827
  • 3
  • 20
  • 26