web-dev-qa-db-fra.com

WebApp (Tomcat-jdbc) Une connexion de base de données en pool avec une exception d'abandon

Cela fait un certain temps que je navigue sur SO et que je mâche mon chapeau, mais je ne trouve pas de solution exacte à mon problème.
Pour résumer, je reçois une superbe trace de pile (abandon org.Apache.Tomcat.jdbc.pool.ConnectionPool) après 60 secondes d’inactivité, ce qui est un comportement normal pour deux threads côté serveur.
J'utilise le regroupement de connexions Tomcat JDBC (org.Apache.Tomcat.jdbc.pool.DataSource) directement
Trace de la pile:

 29 oct. 2012 20:55:50 PM org.Apache.Tomcat.jdbc.pool.ConnectionPool abandon 
 AVERTISSEMENT: la connexion a été abandonnée PooledConnection [com.mysql.jdbc.JDBC4Connection@1ad2916]: Java.lang.Exception 
 à org.Apache.Tomcat.jdbc.pool.ConnectionPool.getThreadDump (ConnectionPool.Java:967) 
 à org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection (ConnectionPool.Java:721) 
 à org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection (ConnectionPool.Java:579) 
 à org.Apache.Tomcat.jdbc.pool.ConnectionPool.getConnection (ConnectionPool.Java:174) 
 à org.Apache.Tomcat.jdbc.pool.DataSourceProxy.getConnection (DataSourceProxy.Java:111) 
 à l'adresse com.getsom.getConnection (DAO.Java:1444) 
 sur com.getsom.PreparedConnection. (PreparedConnection.Java:48) 
 sur com.getsom.Alarms.run (Alarms.Java:492) 

Mes PoolProperties sont configurés comme suit:

    PoolProperties pp = new PoolProperties();

    pp.setUrl( someValidUrl);
    pp.setDriverClassName("com.mysql.jdbc.Driver");
    pp.setUsername( someUser);
    pp.setPassword( somePassword);
    pp.setJmxEnabled( true);
    pp.setTestWhileIdle( true);
    pp.setTestOnBorrow( true);
    pp.setValidationQuery( "SELECT 1");
    pp.setTestOnReturn( false);
    pp.setValidationInterval(30000);
    pp.setTimeBetweenEvictionRunsMillis(30000);
    pp.setMaxActive(100);
    pp.setInitialSize(10);
    pp.setMaxWait(10000);
    pp.setMinEvictableIdleTimeMillis(30000);
    pp.setMinIdle(10);

    pp.setLogAbandoned(true);
    pp.setRemoveAbandoned(true);
    pp.setRemoveAbandonedTimeout(60);
    pp.setJdbcInterceptors("org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.Apache.Tomcat.jdbc.pool.interceptor.StatementFinalizer");    

    setPoolProperties(pp);

J'espérais que setValidationInterval (30000) me sauverait, car 30 secondes ne représentent pas grand chose dans le cycle de vie d'une connexion. En tout cas la question est:
Qu'est-ce qui me manque pour garder cette connexion en vie pour toujours?
Bon à savoir: Pourquoi la temporisation a-t-elle été effectuée dans la fonction qui a déclaré la connexion, alors qu'elle a été invoquée 30 secondes plus tôt.

17
MonoThreaded

Même si j’ai plus de 1 an de retard sur cette page, j’ai trébuché ici, j’ai eu des problèmes similaires et j’avais aussi besoin d’une solution. Alors j'ai pensé partager ce qui a finalement fonctionné pour moi.

Dans mon cas, après avoir trouvé et lu cet article >>> configurationing-jdbc-pool-high-concurrency - Je viens d'ajouter un intercepteur comme celui-ci à la configuration de mon pool;

"org.Apache.Tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"

de sorte que la ligne (à partir de votre code posté ci-dessus) où vous faites setJdbcInterceptors(...) devrait maintenant ressembler à ceci:

p.setJdbcInterceptors(
            "org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState;"
            + "org.Apache.Tomcat.jdbc.pool.interceptor.StatementFinalizer;"
            + "org.Apache.Tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");

Explication - Citant l'article, il est écrit:

Nous voulons nous assurer que lorsque nous détectons que la connexion est toujours utilisée, nous réinitialisons le temporisateur de temporisation, de sorte que la connexion ne soit pas considérée comme abandonnée. Nous faisons cela en insérant un intercepteur.

Chaque fois qu'une instruction est préparée ou qu'une requête est exécutée, le temporisateur réinitialise le temporisateur d'abandon sur le pool de connexions. De cette façon ... faire beaucoup de requêtes et mises à jour, ne pas expirer.

Gardant à l'esprit que vous avez probablement surmonté le problème il y a longtemps, j'espère toujours que cela aidera toute autre personne ayant des problèmes similaires qui heurtent cette page, tout comme je l'ai fait.

À votre santé!

42
CodeBurner

Il suffit d’ajouter l’entrée ci-dessous dans Tomcat7 conf/server.xml ou in context.xml là où votre balise de ressource est présente.

jdbcInterceptors="org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState;
org.Apache.Tomcat.jdbc.pool.interceptor.StatementFinalizer;
org.Apache.Tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
4
Patrikoko

Avez-vous vu les informations sur le site Web de Tomcat relatives à PoolConnection . Peut-être avez-vous besoin de regarder la propriété minEvictableIdleTimeMillis

Pour répondre à votre question, vous arrêtez le délai imparti parce que vous vérifiez les connexions inactives et abandonnées toutes les 30 secondes (voir TimeBetweenEvictionRunsMillis) et que vous définissez un délai d'inactivité expirable à 30 secondes (voir minEvictableIdleTimeMillis), vous vous retrouvez avec ce que vous avez. Vous avez dit que vous receviez cette exception en mode inactif. Je suppose que cette exception résulte de la fermeture d'une connexion inactive, par opposition à l'abandon d'une connexion. A ma connaissance, l'abandon d'une connexion est utilisé pour expirer des requêtes plus longues que prévu (par opposition aux connexions inactives).

Personnellement, je ne voudrais pas avoir de connexions vivantes pour toujours, car elles consommeraient des ressources (c'est-à-dire une connexion à la base de données) sans nécessité. Je jouais avec mes connexions maximales, mes expulsions et mes temps d'inactivité pour optimiser mes propres besoins. Je suppose que vous pouvez définir ces valeurs assez grandes pour être presque pour toujours! Cela dépend vraiment de ce que vous faites bien ...

Désolé je ne pourrais pas être beaucoup plus d'aide ici.

3
ramsinb

Si vous définissez votre source de données dans le fichier context.xml de Tomcat, vous devez ajouter le paramètre ResetAbandonedTimer comme ci-dessous:

jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer"

Après avoir défini ResetAbandonedTimer, le problème a été résolu dans mon application. Je vous demande de me faire savoir s'il existe une relation entre l'intercepteur ResetAbandonedTimer et removeAbandoned = "true" removeAbandonedTimeout = "60"

1
rajesh chaganti

suivre 'removeAbandonedTimeout' dans le fichier de configuration. cela devrait être max requête en cours d'exécution dans l'application. sinon, la connexion sera fermée en cours d'exécution

1
ravindra

Les réponses à cette question m'ont été très utiles.

Bien que dans mon cas, l’intercepteur JDBC "ResetAbandonedTimer" soit déjà configuré.

Cependant, ma requête avait une durée d'exécution supérieure à celle de "removeAbandonedTimeout" que j'avais également configurée. Une fois que j'ai augmenté le "removeAbandonedTimeout" le problème a disparu.

0
buzz