Question

In the context.xml file of my web application, I use:

<Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"
          removeAbandoned="true" removeAbandonedTimeout="60"
          maxActive="30" maxIdle="30" maxWait="10000"
          username="myuser" password="mypwd" driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/mydb"
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" closeMethod="close" 
          validationQuery="select 1" testOnBorrow="true" /> 

It works, but I'm not really sure if 30 simoultaneous connections are enough (the web application is like an auction and there are also admin accesses to count).

Moreover I don't know if

 removeAbandonedTimeout="60"

is too much and how it should be calculated.

Are any post/articles about connection-pooling scenarios, about how to balance resource attributes?

Was it helpful?

Solution

How to configure the database connection pool depends on the characteristics of the application using it. I can give some hints, but ultimately you will have to find out for yourself via (load) testing.

First, read the documentation carefully. The removeAbandoned option for example is a fallback for bad code that does not close/return connections to the pool (from the documentation: Setting this to true can recover db connections from applications that fail to close a connection). If removeAbandoned is used, logAbandoned should also be used (set to true) when you are testing your application. The removeAbandonedTimeout should be tuned to your longest running query (from the documentation: The value should be set to the longest running query your applications might have.).

Ask your DBA if he prefers new connections over idle connections and adjust minEvictableIdleTimeMillis accordingly (some DBAs rather have less new connections (e.g. idle timeout of 1 hour) while others prefer idle connections to be closed as soon as possible (e.g. idle timeout of 30 seconds)).

A maxWait of 10 seconds is likely too low for production. I keep this at 50 seconds (the same timeout a database uses to report deadlocks) so that network- and database-hickups (which will happen) do not cause application errors. On the other hand, when (load) testing, set this value low (like 3 seconds) to get an indication of when the pool is too small (i.e. maxActive is too low).

If application administrators need guaranteed access, you need another (second) pool just to serve these special users. Otherwise there is no guarantee that they can 'get in' and it is likely they must get in when something is wrong and the regular pool is fully exhausted.

I have mentioned load testing before, some extra pointers:

  • Make sure the test database is representative of the production database. A query that runs long on the production database must run long on the test database.
  • Tune pool parameters for testing (so you notice odd behavior fast) and for production (make it is stable as possible and ensure you will notice really bad things).
  • Repeat load testing batch-runs with lower maxActive values until you start to notice a real difference in throughput (or batch runtime). For example, I recently tested an application with 24 threads all doing database actions and started with a maximum pool size of 16. Then did a run with maximum pool size 8 and saw hardly any difference. Then did a run with maximum pool size 4 and noticed a difference. So maximum pool size of 8 was good enough.

Some tips for efficiency:

  • Ensure all code between leasing and releasing a connection ONLY does database actions (e.g. no logging, it sucks time since it flushes to file on disk).
  • Make sure connections are released/closed in a finally block so that connections cannot leak from the pool.
  • Prepare all data used in queries before leasing a connection from the pool.

Happy load testing ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top