<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>full fathom five: MySQL dropping connections and Hibernate</title>
    <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>the blog of Michael Studman</description>
    <item>
      <title>MySQL dropping connections and Hibernate</title>
      <description>&lt;p&gt;
One of the first problems I faced when I deployed this blog was I'd wake up in the morning to check that it was still running from the previous night and find all its database connections hosed and the web app in dire need of a restart. If you're finding this too, here's how I solved it.
&lt;/p&gt;
&lt;p&gt;
Essentially the problem is that MySQL will, after a fairly long period of inactivity (8hrs?), drop database connections. If your application is holding a bunch of these and it is inactive for that period of time then all your connections will be invalid. Unfortunately there is no way to asynchronously detect that you've been disconnected (and thus rectify the problem) so you'll only find out once you try to use the connection.
&lt;/p&gt;
&lt;p&gt;
This in itself is nothing new, all the major web application servers I've used provide some strategy for handling this situation. It's just that Hibernate is such a powerful tool that alleviates so much of the Object-Relational headache that I expected it would have taken care of this for me too. Aparently I'm not alone: &lt;a href="http://www.hibernate.org/117.html#A13"&gt;http://www.hibernate.org/117.html#A13&lt;/a&gt;. This is no criticism of Hibernate, more a compliment, in fact.
&lt;/p&gt;
&lt;p&gt;
The FAQ entry is quite clear - Hibernate's default database connection pool is not well suited to production use - it is not error tolerant so failures like the above will not be recovered from. Luckily, it's no great pain to configure Hibernate so that it uses a decent connection pool that detects and recovers from these problems before your code has to choke on them.
&lt;/p&gt;
&lt;p&gt;
Firstly, you need to decide on a database connection pool - DBCP or C3PO seem to be the two major ones supported directly. Since I've only used DBCP, here's what I did to get going with it.
&lt;/p&gt;
&lt;p&gt;
Your Hibernate configuration probably looks something like this:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;hibernate-configuration&amp;gt;
    &amp;lt;session-factory&amp;gt;
        &amp;lt;!-- properties --&amp;gt;
        &amp;lt;property
         name="connection.driver_class"
           &amp;gt;com.mysql.jdbc.Driver&amp;lt;/property&amp;gt;
        &amp;lt;property
         name="connection.url"
           &amp;gt;jdbc:mysql:/localhost/mydb&amp;lt;/property&amp;gt;
        &amp;lt;property
         name="connection.username"
           &amp;gt;foo&amp;lt;/property&amp;gt;
        &amp;lt;property name="connection.password"
           &amp;gt;bar&amp;lt;/property&amp;gt;
        ...
        ...
    &amp;lt;/session-factory&amp;gt;
&amp;lt;/hibernate-configuration&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
You need to amend this to select DBCP as the connection pool to use and provide it with properties to correctly configure it. Here are the parameters I use:
&lt;/p&gt;
&lt;pre&gt;
        &amp;lt;property name="dbcp.maxActive"&amp;gt;15&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.maxIdle"&amp;gt;5&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.maxWait"&amp;gt;120000&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.whenExhaustedAction"&amp;gt;1&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.testOnBorrow"&amp;gt;true&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.testOnReturn"&amp;gt;true&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.validationQuery"&amp;gt;
            select count(*) from some-table
        &amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.ps.maxActive"&amp;gt;0&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.ps.maxIdle"&amp;gt;0&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.ps.maxWait"&amp;gt;-1&amp;lt;/property&amp;gt;
        &amp;lt;property name="dbcp.ps.whenExhaustedAction"&amp;gt;2&amp;lt;/property&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
Briefly, the significance of each is as follows:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;maxActive - the maximum number of connections in the pool in use at any one time. The pool will not grow beyond this size&lt;/li&gt;
  &lt;li&gt;maxIdle - the maximum number of idle connections in the pool at one time. The pool will shrink in size if there are more than this number of idle connections.&lt;/li&gt;
  &lt;li&gt;maxWait - the maximum milliseconds to wait when blocked on a connection becoming free&lt;/li&gt;
  &lt;li&gt;whenExhaustedAction - what to do when the pool has run out of available connections. 0 - fail, 1 - block, 2 - grow&lt;/li&gt;
  &lt;li&gt;testOnBorrow - should the connection pool test each connection for liveliness before giving to clients. I set this to true.&lt;/li&gt;
  &lt;li&gt;testOnReturn - should the connection pool test each connection for liveliness after the client has given it back. I set this to false.&lt;/li&gt;
  &lt;li&gt;validationQuery - the SQL query to run to determine if the connection is alive - this must return at least one row. I recommend this is a simple select of count(*) on some table with a small number of rows so as to minimise network transfers between the database and the business tier.&lt;/li&gt;
  &lt;li&gt;The last three properties (ps.* for PreparedStatement pooling) are there because Hibernate bombs out if they aren't present. The values I've used cause no PreparedStatement pooling. I leave their explanation as an exercise for the reader.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In case you're wondering why there was no property that selected DBCP as the connection pool implementation, it's because Hibernate infers this from the presence of the associated properties (dbcp.* for DBCP). I'm not sure I like this as it introduces uncertainty as to what will happen when more than one set of properites are present (will the first or last one win, will an exception be thrown?). Still it's only a minor quible.
&lt;/p&gt;
&lt;p&gt;
One final problem you might encounter if deploying to a shared Tomcat instance (for example if you deploy your app through my excellent ISP &lt;a href="http://www.metawerx.com.au"&gt;Metawerx&lt;/a&gt;) is DBCP raising a ClassNotFoundException for your mysql driver even though it can be found by Hibernate and at other points in your code.
&lt;/p&gt;
&lt;p&gt;
The context to this problem was that my ISP adds no jar files to his Tomcat server/lib nor to his shared/lib apart from those that ship with Tomcat. Additionally of note is that Tomcat ships with DBCP. With this knowledge in hand I initially tried putting a mysql jar file in my WEB-INF/lib and expected it to work. Sadly this wasn't the case - Hibernate could happily instantiate the driver but DBCP/JDBC could not when passed the same class name. The problem was related to classloading issues (DBCP was higher up in the classloader tree than MySQL and most classloaders only ask for a class definition up the tree, not down the tree) but was easily solved by placing a copy of DBCP in my web app's WEB-INF/lib directory.
&lt;/p&gt;
&lt;p&gt;
So with your configuration updated and any classloading issues behind you, you should be ready to deploy your application without fear of waking up to screaming collection of broken connections.
&lt;/p&gt;</description>
      <pubDate>Mon, 07 Jun 2004 23:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:6447b8f8-5941-4a59-9cc0-2f8f3dba8d92</guid>
      <author>Michael Studman</author>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate</link>
      <category>Java</category>
      <category>Java/J2EE</category>
      <category>mysql</category>
      <category>hibernate</category>
      <category>pooling</category>
      <category>codegargle</category>
      <trackback:ping>http://www.michaelstudman.com/fullfathomfive/articles/trackback/57</trackback:ping>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Michael Studman</title>
      <description>&lt;p&gt;Hi Zsolt.&lt;/p&gt;

&lt;p&gt;Actually, using the autoReconnect parameter is not recommended. Here's the developer of the MySQL JDBC driver explaining why:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.theserverside.com/news/thread.tss?thread_id=24137#111947"&gt;http://www.theserverside.com/news/thread.tss?thread_id=24137#111947&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To be honest, trying this parameter was my first course of action but it didn't work for me.&lt;/p&gt;

&lt;p&gt;Michael.&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jun 2004 22:49:17 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:f6838cc1-2c33-4160-ac3f-434ffedda6cb</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-64</link>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Matt Quail</title>
      <description>&lt;p&gt;Dude! I've been trying to debug a problem in a production enviroment that I can't reproduce in dev... this is probably it! yay!&lt;/p&gt;

&lt;p&gt;=Matt&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jun 2004 22:18:08 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:85faca81-18fe-4540-b9dc-6bd4e59b818e</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-63</link>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Zsolt</title>
      <description>&lt;p&gt;You can disable the MySQL 8hr timeout by adding autoReconnect=true to your jdbc connection url.&lt;/p&gt;

&lt;p&gt;The autoReconnect=true argument to the url makes sure that the mm.mysql JDBC Driver will automatically reconnect if mysqld closed the connection.  mysqld by default closes idle connections after 8 hours.&lt;/p&gt;

&lt;p&gt;jdbc:mysql:/localhost/mydb?autoReconnect=true&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jun 2004 16:26:43 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:a1735e3f-f9f2-4ef7-a9cb-7c4ad501cf25</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-62</link>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Michael Studman</title>
      <description>&lt;p&gt;Thanks for the SQL tip, Jari. It's quite obvious, really, but overlooked by me for some unknown reason.&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jun 2004 09:52:17 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:1b227f14-2f9f-4b17-bb9e-9a129945d441</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-61</link>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Jari Aarniala</title>
      <description>&lt;p&gt;select 1&lt;/p&gt;

&lt;p&gt;is a valid (and the most simple) validation query, that's what I use&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jun 2004 06:23:43 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:f88a5a7a-87ee-4d1b-ab1d-4ef76cc0b989</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-60</link>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Josh</title>
      <description>&lt;p&gt;related:
&lt;a href="http://blog.w1c.ca/index.do?post=40288383fca0998000fca0a5232f0003"&gt;http://blog.w1c.ca/index.do?post=40288383fca0998000fca0a5232f0003&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 10 Jun 2004 01:14:52 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:c82676ab-2cd4-4770-b903-1e95499b3f76</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-59</link>
    </item>
    <item>
      <title>"MySQL dropping connections and Hibernate" by Mr Ed</title>
      <description>&lt;p&gt;&amp;gt; One of the first problems I faced when I deployed this blog 
&amp;gt; was I'd wake up in the morning ...&lt;/p&gt;

&lt;p&gt;That's your main problem right there - waking up in the morning. Everything looks better in the afternoon.&lt;/p&gt;</description>
      <pubDate>Tue, 08 Jun 2004 22:35:07 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:5fae0481-ab4b-4481-8099-b09c737dc6f8</guid>
      <link>http://www.michaelstudman.com/fullfathomfive/articles/2004/06/07/mysql-dropping-connections-and-hibernate#comment-58</link>
    </item>
  </channel>
</rss>
