Cours de DB connections!
Je suis à court d'un Spring/Hibernate pour se connecter à MySQL configuration à l'aide de c3p0 que mon pool de connexion. Pour une étrange raison, il est à court de connexions lorsque le système est en charge (bien sûr).
Le site a été assez stable jusqu'à ce que nous avons commencé à atteindre un nouveau niveau de trafic (plus d'une centaine d'utilisateurs simultanés). À ce stade de la DB se fondre (peg de la CPU). Ma première action a été dans l'application afin d'améliorer les performances grâce à une vaste mise en cache et l'optimisation de requêtes, etc.
Maintenant il suffit d'exécuter de connexions par intermittence. Il ne semblent même pas qui dépend de la charge. Plus sur le temps qui me fait penser que c'est une fuite, mais pour la vie de moi je ne peux pas comprendre d'où il serait à venir.
WARN [2011-03-07 17:19:42,409] [TP-Processor38] (JDBCExceptionReporter.java:100) - SQL Error: 0, SQLState: null
ERROR [2011-03-07 17:19:42,409] [TP-Processor38] (JDBCExceptionReporter.java:101) - An attempt by a client to checkout a Connection has timed out.
ERROR [2011-03-07 17:19:42,410] [TP-Processor38] (HttpHeadFilter.java:46) - There was a problem passing thru filter:/is-this-guy-crazy-or-just-a-huge-dancing-with-the-stars-fan
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not execute query
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:659)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:527)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
Voici ma configuration:
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="rootDataSource" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingLocations" value="classpath:hibernate-mapping.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.provider_class">net.sf.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.generate_statistics">true</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.connection.zeroDateTimeBehavior">convertToNull</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">${hibernate.bytecode.use_reflection_optimizer}</prop>
<!--<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>-->
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
<!--Actually, it seems the following property affects batch size (or explicit per relationship in the mapping)-->
<!--<prop key="hibernate.default_batch_fetch_size">${hibernate.jdbc.batch_size}</prop>-->
</props>
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="rootDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialPoolSize" value="20" />
<property name="maxPoolSize" value="200" />
<property name="checkoutTimeout" value="30000" />
<property name="maxStatements" value="180" />
<property name="minPoolSize">
<value>${hibernate.c3p0.minPoolSize}</value>
</property>
<property name="acquireRetryAttempts">
<value>${hibernate.c3p0.acquireRetryAttempts}</value>
</property>
<property name="acquireIncrement">
<value>${hibernate.c3p0.acquireIncrement}</value>
</property>
<property name="idleConnectionTestPeriod">
<value>${hibernate.c3p0.idleConnectionTestPeriod}</value>
</property>
<property name="maxIdleTime">
<value>${hibernate.c3p0.maxIdleTime}</value>
</property>
<property name="maxIdleTimeExcessConnections">
<value>${hibernate.c3p0.maxIdleTimeExcessConnections}</value>
</property>
<property name="maxConnectionAge">
<value>${hibernate.c3p0.maxConnectionAge}</value>
</property>
<property name="preferredTestQuery">
<value>${hibernate.c3p0.preferredTestQuery}</value>
</property>
<property name="testConnectionOnCheckin">
<value>${hibernate.c3p0.testConnectionOnCheckin}</value>
</property>
<property name="numHelperThreads">
<value>${hibernate.c3p0.numHelperThreads}</value>
</property>
<property name="unreturnedConnectionTimeout">
<value>${hibernate.c3p0.unreturnedConnectionTimeout}</value>
</property>
<property name="debugUnreturnedConnectionStackTraces">
<value>${hibernate.c3p0.debugUnreturnedConnectionStackTraces}</value>
</property>
<property name="automaticTestTable">
<value>${hibernate.c3p0.automaticTestTable}</value>
</property>
</bean>
hibernate.c3p0.acquireIncrement=5
hibernate.c3p0.minPoolSize=20
hibernate.c3p0.acquireRetryAttempts=30
hibernate.c3p0.idleConnectionTestPeriod=3600
hibernate.c3p0.maxIdleTime=7200
hibernate.c3p0.maxIdleTimeExcessConnections=1800
hibernate.c3p0.maxConnectionAge=14400
hibernate.c3p0.preferredTestQuery=select 1;
hibernate.c3p0.testConnectionOnCheckin=false
hibernate.c3p0.numHelperThreads=6
hibernate.c3p0.unreturnedConnectionTimeout=0
hibernate.c3p0.debugUnreturnedConnectionStackTraces=true
hibernate.c3p0.automaticTestTable=test_connection;
Je suis en cours d'exécution OpenSessionInViewInterceptor qui devrait être la fermeture de la connexion:
<bean id="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="flushModeName">
<value>FLUSH_AUTO</value>
</property>
</bean>
Je suis également en utilisant le printemps les annotations @Transactional depuis que j'ai réutiliser mes services en non web paroi de code.
Il ya vraiment seulement deux options ici, c'est de ne pas libérer les connexions lorsque vous avez terminé. Ou il est encore accroché à bavarder sur la base de données, comme c'est d'essayer d'obtenir le son pantalon.
Si quelqu'un a des idées, je serais reconnaissant
thx
SUIVI: En fin de compte, il s'avère que j'ai une fuite des connexions grâce à l'utilisation de OpenSessionInViewInterceptor. J'ai eu spring security fonctionne comme un filtre de façon à elle de se connecter à la DB et de ne jamais les fermer. La solution était de déplacer le OpenSessionInViewInterceptor à OpenSessionInViewFilter.
OriginalL'auteur matsientst | 2011-03-08
Vous devez vous connecter pour publier un commentaire.
Il est assez peu probable que
@Transactional
fuites de connexions - dans le cas contraire, votre site serait d'arrêter de travailler après les 100 premières demandes.Mais il est une autre raison pourquoi cela se produit:
Peut-être vous avez défini un délai d'attente pour la "mort" de connexions et de certaines requêtes prendre plus de temps que cela. Cela signifie que votre piscine retiré une longue connexion est "mort" de la piscine et de la demande à un autre de la DB - jusqu'à ce que le DB tire la plug.
De débogage, activer la journalisation pour votre pool de connexion, de sorte que vous pouvez voir quand il demande de nouvelles connexions.
OriginalL'auteur Aaron Digulla
Essayez d'activer la journalisation et le réglage de la
c3p0.debugUnreturnedConnectionStackTraces
true à la propriété. Également définirc3p0.unreturnedConnectionTimeout
à quelque chose de plus petit que la moyenne de la requête (1 sec?). Puis quelque chose qui prend plus de temps que le délai d'attente enregistre une trace de la pile. Cela devrait vous permettre d'affiner les choses assez rapidement.Si il n'y a pas de motif sur les traces de pile, il pourrait être simplement que votre piscine est trop petite. Vous avez dit 100 utilisateurs simultanés, mais aucune idée du nombre de requêtes par seconde c'est? Si c'est 100 requêtes par seconde et vous avez 20 connexions, puis chaque exécution de sql doit prendre moins de 200 ms (20 connexions => 20 total des secondes de travail par seconde de l'horloge du mur le temps de faire de 100 des requêtes).
OriginalL'auteur AngerClown
Quelle que soit la configuration que vous avez pour C3P0 (par le biais de la mise en veille), vous pourriez avoir une restriction imposée par MySQL lui-même. Gardez à l'esprit que, par défaut, le nombre maximum de connexions autorisées par MySQL est à 100! Donc, même si vous dites à C3P0 pour piscine jusqu'à 200, 500 ou 1000 connexions, ce sera impossible à atteindre. Ouvrez un shell MySQL à l'aide de:
Et tapez la commande suivante pour obtenir le nombre maximum de connexions autorisées:
Si le nombre retourné est trop faible pour votre application, envisagez de le modifier (modifier ma.cnf de fichier, généralement situé à l'intérieur de /etc/mysql/sur les systèmes Linux).
OriginalL'auteur Pantelis Sopasakis
J'ai aussi eu ce problème. La cause est que l'utilisateur n'a pas de subventions pour l'accueil, parce que le /etc/hosts entrée a été modifiée.
OriginalL'auteur Martin Krueger
J'ai aussi eu ce problème et je l'ai résolu en définissant la propriété checkoutTimeout de C3P0 à 0 au lieu d'une valeur supérieure à 0.
En fait j'ai eu beaucoup de threads en attente pour une connexion et après 10s, les mêmes erreurs que la vôtre s'est produite.
Voir la doc ici : http://www.mchange.com/projects/c3p0/#checkoutTimeout
OriginalL'auteur c4k