2009-04-11 8 views
1

Nous hébergeons un service (servlet tournant sur jboss), qui reçoit quelque chose comme 5-6 requêtes par seconde. Chaque requête doit se connecter à mysql via hibernate. La plupart de nos demandes sont sélectionnées, avec une insertion/mise à jour chaque 5ème/6ème demande. La connexion à hibernate mysql est expirée après la période d'expiration de la connexion mysql (8 heures). Même après avoir fait une requête ping à notre service, toutes les heures, la connexion mysql est parfois déconnectée au hasard après un jour ou deux. Nous voulons que Hibernate se reconnecte au cas où la connexion est déconnectée pour une raison quelconque, et maintenez le nombre de connexions que nous voulons.Mise en pool de connexion Hibernate/mysql

Nous avons essayé C3P0, avec la configuration suivante:

<property name=c3p0.acquire_increment>1</property> 
<property name=c3p0.idle_test_period>3600</property> 
<property name=c3p0.max_statements>0</property> 
<property name=c3p0.min_size>1</property> 
<property name=c3p0.timeout>3605</property> 
<property name=hibernate.c3p0.preferredTestQuery>select 1;</property> 

taille Hibernate connection_pool a été réglé sur 1.

Cela a le problème délai/déconnexion disparaître. Mais nous avons commencé à faire face à un autre problème. Longue attente Normalement, la durée de la demande est de 2-3 ms pour la sélection et de 40-50 ms pour l'insertion/la mise à jour. Mais, après avoir utilisé la configuration C3P0 ci-dessus, nous avons vu que chaque requête terminée après une mise à jour prenait plus d'une minute et parfois même 4-5 minutes! À partir de nos journaux, il semblait que, de manière aléatoire, une demande de sélection serait bloquée et ne pourrait se terminer qu'après la réception et le service d'une demande de mise à jour.

Le problème ci-dessus disparaît si nous supprimons la configuration C3P0. Quelqu'un peut-il suggérer ce que nous pourrions faire de mal?

Voici la config de mise en veille prolongée complet pour référence:

<?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="connection.driver_class">com.mysql.jdbc.Driver</property> 
     <property name="connection.url">jdbc:mysql://xxx.xxx.xxx</property> 
     <property name="connection.username">xxx</property> 
     <property name="connection.password">xxx</property> 
     <property name="connection.pool_size">1</property> 
     <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
     <property name="current_session_context_class">thread</property> 
     <property name="hibernate.cache.use_query_cache">false</property> 
     <property name="hibernate.cache.use_second_level_cache">false</property> 
     <property name="show_sql">true</property> 

     <!-- Transaction isolation 2 = READ_COMMITTED --> 
     <property name="connection.isolation">2</property> 
     <property name="connection.autocommit">true</property> 

     <!-- configuration pool via c3p0--> 
     <property name="c3p0.acquire_increment">1</property> 
     <property name="c3p0.idle_test_period">3600</property> <!-- seconds --> 
     <property name="c3p0.max_size">1</property> 
     <property name="c3p0.max_statements">0</property> 
     <property name="c3p0.min_size">1</property> 
     <property name="c3p0.timeout">3605</property> <!-- seconds --> 
     <property name="hibernate.c3p0.preferredTestQuery">select 1;</property> 

    </session-factory> 
</hibernate-configuration> 

Répondre

1

Je recommande d'abandonner C3P0 et en utilisant le service de nommage JNDI et le regroupement de connexions qui fournit JBOSS.

Assurez-vous de fermer les connexions correctement et de les renvoyer dans la piscine. Connectez-vous, interrogez, fermez, tout dans la portée la plus étroite possible. Aucune connexion ne devrait être suspendue pendant huit heures.

Quelques liens plus pourraient être pertinents: http://www.hibernate.org/117.html et http://www.informit.com/articles/article.aspx?p=353736&seqNum=4 en ce qui concerne les connexions Hibernate et de fermeture, et ce bug MySQL qui cite des problèmes avec MySQL, Hibernate et les connexions: http://bugs.mysql.com/bug.php?id=10917

+0

hmmm, actuellement, nous laissons complètement la gestion des connexions en mode hibernation, c'est-à-dire que nous demandons uniquement à hibernate pour la connexion actuelle (getCurrentConnection()), puis nous exécutons la requête. Nous n'ouvrons ou ne fermons jamais une connexion explicitement dans notre code. Probablement, nous devons relooker à cette stratégie. – ashweta

+0

Mais nous avons aussi une exigence de haute performance aussi (<50ms). Nous ne pouvons pas nous permettre d'ouvrir et de fermer une connexion db à chaque fois qu'une demande arrive. Donc, en fait, nous devons regrouper les connexions ouvertes qui sont maintenues par hibernate/JNDI, que nous pouvons utiliser sans jamais les fermer nous-mêmes. – ashweta

+0

@ashweta: Vous devez lire ceci - http://www.hibernate.org/117.html. Rechercher "Hibernate fuit les connexions JDBC!" Je dois fermer la session. En ce qui concerne la performance, c'est pourquoi vous avez des piscines. "Close" signifie dans ce cas "retour à la piscine". – duffymo

1

Quelque chose semble mal avec votre configuration. Tous les paramètres de configuration doivent se trouver dans l'espace de noms hibernate.c3p0, pas c3p0. *.

Mais ce n'est probablement pas le problème. Je pense que votre pool n'est probablement qu'une connexion volumineuse et que vous rencontrez des problèmes de contention de ressources quelque part. Très probablement ne pas libérer une connexion où vous devriez, ou un blocage sur certaines données. Essayez de définir maxPoolsize à quelque chose de plus élevé, comme 2 et voir si le problème est atténué. Cela signifierait probablement que vous ne retournez pas correctement les connexions.

0

La documentation JBoss Hibernate spécifiquement déclare ne pas utiliser le gestionnaire connexion piscine Hibernate pour les systèmes non-production (comme hypersonique - Je ne sais vraiment pas pourquoi ils prennent la peine de transporter des composants buggy connus). Comme précédemment commenté, utilisez l'installation standard JBoss <datasource> et pool-manager associé (et configurez si nécessaire). En cas de malentendu, les méthodes open() et close() sont remplacées par le gestionnaire de connexions. Même l'objet Connection n'est pas une connexion directe à la base de données mais plutôt un handle pour le gestionnaire de pool.

La mise en œuvre lors de l'obtention d'une nouvelle connexion (aka ouverte) est de demander une connexion de la piscine (qui, pour l'efficacité est déjà ouvert et, si elle est configurée en utilisant la propriété <prepared-statement-cache-size> dans la définition datasource, a également les anciens PreparedStatement s encore liés à cela Connection). Cet appel est plus efficace. Lorsque close() est appelé sur la connexion (à nouveau, implémentée par le gestionnaire de pool), l'état de référence de connexion est simplement changé en «disponible» par rapport à la fermeture de la connexion de base de données réelle. C'est aussi plus efficace. Par conséquent, il est recommandé que la plus petite portée possible des appels open/exec/close soit faite pour maximiser l'utilisation multi-thread des connexions disponibles dans le pool.

Questions connexes