Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Cannot open Connection

33 views
Skip to first unread message

Daniel Urban

unread,
Feb 26, 2011, 7:10:56 AM2/26/11
to
Hallo,

ich habe ein Problem mit meiner Web-Anwendung beim Öffnen einer Connection.
Vielleicht kann mir jemand einen Hinweis geben?

Meine Anwendung greift auf eine Oracle 9 Datenbank mit JDBC zu. Die
Connections werden im JBoss im Connection Pool gehalten. Ich verwende
Hibernate als O/R Mapper. Für das Handling der Hibernate Session wird der
OpenSessionInViewFilter von Spring verwendet. Für das Management der
Transaktionen wird Spring mittels AOP verwendet.

Die Anwendung läuft einige Tage ohne Probleme, doch dann liefert die
Anwendung bei jedem Zugriff auf die Datenbank folgende Excpetion von
Hibernate:

org.hibernate.exception.GenericJDBCException: Cannot open connection
at
org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at
org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
at
org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:426)
at
org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144)
at
org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:140)

Die zugrundeliegende Exception ist:

Caused by: org.jboss.util.NestedSQLException: No ManagedConnections
available within configured blocking timeout ( 30000 [ms] ); - nested
throwable: (javax.resource.ResourceException: No ManagedConnections
available within configured blocking timeout ( 30000 [ms] ))
at
org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:95)
at
org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at
org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:423)

Die zugrundeliegende Exception ist:

Caused by: javax.resource.ResourceException: No ManagedConnections available
within configured blocking timeout ( 30000 [ms] )
at
org.jboss.resource.connectionmanager.InternalManagedConnectionPool.getConnection(InternalManagedConnectionPool.java:295)
at
org.jboss.resource.connectionmanager.JBossManagedConnectionPool$BasePool.getConnection(JBossManagedConnectionPool.java:644)
at
org.jboss.resource.connectionmanager.BaseConnectionManager2.getManagedConnection(BaseConnectionManager2.java:404)
at
org.jboss.resource.connectionmanager.TxConnectionManager.getManagedConnection(TxConnectionManager.java:381)
at
org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:496)
at
org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941)
at
org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89)

In der JMX-Console vom JBoss wird zum Connection Pool folgendes angezeigt:

MaxConnectionsInUseCount : 30
MaxSize : 30
ConnectionDestroyedCount : 203
ConnectionCount : 30
ConnectionCreatedCount: 233
InUseConnectionCount : 30
IdleTimeoutMinutes : 30

Ich habe auch einen Heap Dump gezogen in dem ich 30 Instanzen der Klasse
"WrappedConnectionJDK5" sehe. Alle Instanzen haben den Wert "false" im
Attribute "closed" und sind daher wohl noch offen.

In Oracle finde ich auch 30 Sessions mit der Web-Anwedung, die alle auf
"inactive" stehen. Die Sessions sind teilweise schon zwei Wochen alt.

Ich habe auch einen Stack Dump gezogen. Ich konnte keinen Thread finden, der
noch in einer Methode war, die auf die Datenbank zugreift.

Meine Überlegung war zunächst, dass die Anzahl der Connections das Limit
erreicht hätte. Dagagen spricht meiner Meinung nach die Fehlermeldung in der
Excpetion. Außerdem spricht der Stack Dump dagegen, der keine Methoden mehr
anzeigt, die auf die Datenbank zugreifen. Auch die inaktiven Sessions in
Oracle sprechen dagegen.

Meine zweite Überlegung war, dass eventuelle eine Connection nicht
geschlossen wurde. Dagagen spricht aber, dass ich mit Spring niemals selber
eine Connection schliesse. Außerdem vermute ich, dass bei Verwendung eines
Connection Pools sowieso nicht wirklich geschlossen wird, sondern offen
zurück in den Pool gelegt wird.

Meine dritte Vermutung war, dass es einen Netzwerkfehler gibt und die
Anwendung die Datenbank nicht erreicht. Aber ich würde vermuten, dass dann
die Session in der Datenbank auch abgeräumt werden müsste. Es sollte dort
wohl einen Timeout geben und der sollte auch kleiner 2 Wochen sein.

Also muss ich wohl irgend etwas nicht richtig vertanden haben. Daher hier
meine Fragen:

1. Welche Bedeutung hat "InUseConnectionCount "? Wird hier die Anzahl der
gerade verwendeten oder die Anzahl der im Pool befindlichen Connections
angegeben? Oder ist es die Summe der beiden Werte?

2. In welchen Fällen wird eine Connection aus dem Pool destroyed?

3. Wenn Spring nach Beendigung der Methode die Connection zurück in den Pool
gibt, wird die Connection dann automatisch auf closed gesetzt?

4. Falls 2. stimmt, gibt es dann Fälle, in denen Spring die Connection nicht
automatisch auf "closed" setzt?

5. Muss eine Connection im Connection Pool closed sein? Oder darf sie nicht
"closed" sein?

6. Wenn eine Session in Oracle auf "inactive" steht, bedeutet dies, dass die
Connection nicht benutzt wird oder dass es auch keine Verbindung mehr zur
Web-Anwendung gibt?

7. Wenn der Connection Pool sein Limit erreicht, wird dann eine
entsprechende Fehlermeldung ausgegeben? Ich glaube im Internet gelesen zu
haben, dass eine Meldung derart, dass die Anzahl der Connections
überschritten wurde, ausgegeben wird.

Vielen Dank.

Gruß,

Daniel


Daniel Urban

unread,
Feb 26, 2011, 10:20:19 AM2/26/11
to
"Daniel Urban"
[...]

> In der JMX-Console vom JBoss wird zum Connection Pool folgendes angezeigt:
>
> MaxConnectionsInUseCount : 30
> MaxSize : 30
> ConnectionDestroyedCount : 203
> ConnectionCount : 30
> ConnectionCreatedCount: 233
> InUseConnectionCount : 30
> IdleTimeoutMinutes : 30
[...]

Okay. Ich habe mir nun den Heap Dump noch einmal ganz genau angeschaut.
Dabei konnte ich ein paar meiner Fragen beantworten.

> 1. Welche Bedeutung hat "InUseConnectionCount "? Wird hier die Anzahl der
> gerade verwendeten oder die Anzahl der im Pool befindlichen Connections
> angegeben? Oder ist es die Summe der beiden Werte?

Der Wert kommt aus dem InternalManagedConnectionPool und dem dortigen Member
checkedOut. Es handelt sich um die aus dem Pool entfernten Connections.

Im Heap konnte ich entsprechend auch sehen, dass die Methode
getAvailableConnections() die Anzahl der Locks mitteilt. Diese ist auch 30.
Die Liste der verfügbaren Connection event listeners ist 0. D.h. der Pool
ist leer.

> 2. In welchen Fällen wird eine Connection aus dem Pool destroyed?

Offenbar werden alle Connections destroyed, wenn flush() aufgerufen wird.
Ansonsten werden die im Pool befindlichen Connections nach einem Timeout
entfernt. Auch bei der Rückgabe der Connection an den Pool kann ggf. eine
Connection destroyed werden.

> 7. Wenn der Connection Pool sein Limit erreicht, wird dann eine
> entsprechende Fehlermeldung ausgegeben? Ich glaube im Internet gelesen zu
> haben, dass eine Meldung derart, dass die Anzahl der Connections
> überschritten wurde, ausgegeben wird.

Die angegebene Fehlermeldung "No ManagedConnections available within
configured blocking timeout " bedeutet, dass alls Locks vergeben sind. D.h.
alle Connections aus dem Pool entfernt wurden.

Gruß,

Daniel

Daniel Urban

unread,
Feb 28, 2011, 5:12:08 AM2/28/11
to
"Daniel Urban"
[...]

> Ich habe auch einen Heap Dump gezogen in dem ich 30 Instanzen der Klasse
> "WrappedConnectionJDK5" sehe. Alle Instanzen haben den Wert "false" im
> Attribute "closed" und sind daher wohl noch offen.

Ich habe mir die Connections noch einmal genauer angeschaut und
herausgefunden, dass sie alle um die gleiche Uhrzeit geöffnet wurden.
Dadurch kam ich auf die Idee, dass es sich um einen Quartz Job handelt.

In dem Job wird der HibernateDaoSupport verwendet. Der Code ruft
getSession() auf, released die Session aber nicht wieder. Im GUI-Fall ist
das unproblematisch, weil der OpenSessioninViewFilter die Session erzeugt
und auch wieder released. Im Quartz-Fall erzeugt getSession() aber eine neue
Session und niemand kümmert sich darum, dass sie wieder geschlossen wird.
Ich vermute, dass dadurch die Connection offen bleibt.

Allerdings wundere ich mich ein wenig, dass die Session vom GC abgeräumt
wird, aber die Connection nicht automatisch zurückgegeben wird. Vermutlich
liegt es an dem nicht immer zuverlässig funktionierenden Finalizer oder er
wurde gar nicht verwendet.

Gruß,

Daniel

Daniel Urban

unread,
Mar 2, 2011, 5:28:20 AM3/2/11
to
"Daniel Urban"
[...]

> In dem Job wird der HibernateDaoSupport verwendet. Der Code ruft
> getSession() auf, released die Session aber nicht wieder. Im GUI-Fall ist
> das unproblematisch, weil der OpenSessioninViewFilter die Session erzeugt
> und auch wieder released. Im Quartz-Fall erzeugt getSession() aber eine
> neue Session und niemand kümmert sich darum, dass sie wieder geschlossen
> wird. Ich vermute, dass dadurch die Connection offen bleibt.

Kann mir jemand sagen, ob es so etwas wie den OpenSessionInViewFilter von
Spring auch für Quartz Jobs gibt?

Gruß,

Daniel

Daniel Urban

unread,
Mar 6, 2011, 3:44:31 AM3/6/11
to
"Daniel Urban"

Habe mitterlweile den HibernateInterceptor gefunden, der gewünschte
Funktionalität anbietet:

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/orm/hibernate3/HibernateInterceptor.html

Die Einbindung mit Quartz ist dann auch recht einfach:

http://raulraja.com/2009/06/13/aop-spring-hibernate-sessions-for-background-threads-jobs/

Gruß,

Daniel

0 new messages