En tomcat 6.0.X usando el driver jdbc mysql-connector-java-5.0.6 con autoreconexión, hemos comprobado que pasado un periodo de unas horas de inactividad, se produce una excepción al conectar con la base de datos mysql 5 a través de un pool de conexiones.
El error obtenido es el siguiente (en catalina.out o tomcat.log, según sea el caso):
Last packet sent to the server was 1 ms ago. 2010-11-04 05:22:47,952 [ajp-8009-191] ERROR {} - [Communications link failure due to underlying exception: ** BEGIN NESTED EXCEPTION ** java.io.EOFException STACKTRACE: java.io.EOFException at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1956) .... .... ** END NESTED EXCEPTION **
Hemos comprobado que el tiempo de inactividad se corresponde con la variable de mysql wait_timeout: Que es el número de segundos que el servidor espera actividad en una conexión no interactiva antes de cerrarla.
Para solventar este problema, podría pensarse quitar la cadena de autoreconexión, en la llamada al driver (por ej. context.xml o server.xml):
jdbc:mysql://localhost:3306/data_base?autoReconnect=true
por
jdbc:mysql://localhost:3306/data_base
Ya que el propio pool de conexiones se encarga de establecer la conexión con la base de datos, pero no es suficente.
Es necesario añadir lo siguiente al la configuración del dbcp:
validationQuery=”SELECT 1″
testOnBorrow=”true”
Generalmente en server.xml o context.xml, por ejemeplo:
< Resource name="jdbc/elrecurso" auth="Container" type="javax.sql.DataSource" username="elusuario" password="laclave" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/labasededatos" maxActive="10" maxIdle="4" validationQuery="SELECT 1" testOnBorrow="true" / >
Como funciona:
- Antes de devolver la conexión desde el pool a la aplicación, dbcp ejecuta la petición “SELECT 1" sobre la conexión para ver si sigue viva. Es lo que hace validationQuery.
- testOnBorrow, si es true llama al dbcp para realizar la comprobación antes de devolver la conexión a la aplicación.