OVH Cloud OVH Cloud

[Struts][Oracle][Hibernate] Trop de curseurs ouverts.

10 réponses
Avatar
Stephane Zuckerman
Bonjour,

Je programme sur une base Oracle à l'aide du framework Struts, et de
Hibernate pour dialoguer avec la base (jusque là, pas de problème, c'était
dans le sujet du post ;-) ). Pour chaque requête HTTP, l'application ouvre
une session Hibernate, consulte/met à jour/insère des données dans la
base, et automatiquement, à la sorte de l'action, referme la session
Hibernate (le RequestProcessor a été étendu, et on a la certitude que
session.close() est bien appelé).

Seulement voilà, malgré toutes ces précautions, nous avons quand même une
requête (qui semble générée par Hibernate - la requête en elle-même
n'existe pas dans notre code) qui semble ouvrir 76 curseurs dans la base
Oracle. Après épluchage de logs, je ne trouve pas de raison valable.
La FAQ d'Hibernate semble indiquer qu'en cas de "connection pooling", cela
peut poser des problèmes de "fuites" de connexions, et suggèrent de
positionner une variable (hibernate.connection.pool_size) à 0.

Je tiens à préciser qu'en montant le nombre maximum de curseurs autorisés
dans Oracle à un valeur assez grande (ici 600), le problème n'apparaît
plus. Cependant, rien ne me dit que la prochaine fois, l'une de ces
requêtes générées automatiquement ne vont pas encore faire des leurs.

Ma question est donc de savoir ce qui, dans Oracle ou dans Hibernate (et
éventuellement Struts), pourrait générer autant de connexions simultanées
alors qu'il s'agit d'une simple requête du type

(version HQL)
"from Table as t where t.idtable = <id> and t.typeprop = <prop>"

(version SQL)
"select * from Table where idtable = <id> and typeprop = <prop>"

--
"Je deteste les ordinateurs : ils font toujours ce que je dis, jamais
ce que je veux !"
"The obvious mathematical breakthrough would be development of an easy way
to factor large prime numbers." (Bill Gates, The Road Ahead)

10 réponses

Avatar
Trognon Patrice
Stephane Zuckerman wrote:

Bonjour,

Je programme sur une base Oracle à l'aide du framework Struts, et de
Hibernate pour dialoguer avec la base (jusque là, pas de problème, c'était
dans le sujet du post ;-) ). Pour chaque requête HTTP, l'application ouvre
une session Hibernate, consulte/met à jour/insère des données dans la
base, et automatiquement, à la sorte de l'action, referme la session
Hibernate (le RequestProcessor a été étendu, et on a la certitude que
session.close() est bien appelé).

Seulement voilà, malgré toutes ces précautions, nous avons quand même une
requête (qui semble générée par Hibernate - la requête en elle-même
n'existe pas dans notre code) qui semble ouvrir 76 curseurs dans la base
Oracle. Après épluchage de logs, je ne trouve pas de raison valable.
La FAQ d'Hibernate semble indiquer qu'en cas de "connection pooling", cela
peut poser des problèmes de "fuites" de connexions, et suggèrent de
positionner une variable (hibernate.connection.pool_size) à 0.

Je tiens à préciser qu'en montant le nombre maximum de curseurs autorisés
dans Oracle à un valeur assez grande (ici 600), le problème n'apparaît
plus. Cependant, rien ne me dit que la prochaine fois, l'une de ces
requêtes générées automatiquement ne vont pas encore faire des leurs.

Ma question est donc de savoir ce qui, dans Oracle ou dans Hibernate (et
éventuellement Struts), pourrait générer autant de connexions simultanées
alors qu'il s'agit d'une simple requête du type

(version HQL)
"from Table as t where t.idtable = <id> and t.typeprop = <prop>"

(version SQL)
"select * from Table where idtable = <id> and typeprop = <prop>"

--
"Je deteste les ordinateurs : ils font toujours ce que je dis, jamais
ce que je veux !"
"The obvious mathematical breakthrough would be development of an easy way
to factor large prime numbers." (Bill Gates, The Road Ahead)


Hi,

Une question avant d'apporter un début de réponse :

Quel driver JDBC utilises tu, celui fournit avec Oracle ?

--
Cordialement,

Patrice Trognon
http://www.javadevel.com

Avatar
Stephane Zuckerman
[Ma vie, mes problèmes :-)]

Une question avant d'apporter un début de réponse :

Quel driver JDBC utilises tu, celui fournit avec Oracle ?


J'utilise celui trouvé sur le site d'oracle oui (ojdbc14-1.jar).

--
"Je deteste les ordinateurs : ils font toujours ce que je dis, jamais ce
que je veux !"
"The obvious mathematical breakthrough would be development of an easy
way to factor large prime numbers." (Bill Gates, The Road Ahead)

Avatar
Trognon Patrice
Stephane Zuckerman wrote:

[Ma vie, mes problèmes :-)]

Une question avant d'apporter un début de réponse :

Quel driver JDBC utilises tu, celui fournit avec Oracle ?


J'utilise celui trouvé sur le site d'oracle oui (ojdbc14-1.jar).



Ok, alors ton problème ne vient pas forcement d'Hibernate (meme si il
existe peut etre un autre soucis de ce coté la ..., a checker).

Perso j'ai aussi un projet sur Oracle ou je finis par peter en
too many cursors open, j'ai bien vérifier mon code je ferme
tout correctement et ca fini par peter.

Augmenter le nombre de curseurs sur Oracle n'étant repousser le problème.

En fait après quelques recherches j'ai pu lire que le problème
vient du driver JDBC d'Oracle.

J'ai donc trouvé une super solution, je vais utiliser un autre driver JDBC :))

Voir sur le site de sun pour en downloader un.

J'en ai parlé avec des potes qui ont eu le même problème le fait de passer
sur un driver JDBC d'un autre fournisseur a solutionné le problème.

Voila.

PS : pas encore testé avec le nouveau driver car je suis en plein dev
sur un autre projet, je rebasculerai sur ce problème en sept.

--
Cordialement,

Patrice Trognon
http://wwW.javadevel.com


Avatar
Simon OUALID

J'utilise celui trouvé sur le site d'oracle oui (ojdbc14-1.jar).



Perso j'ai aussi un projet sur Oracle ou je finis par peter en
too many cursors open, j'ai bien vérifier mon code je ferme
tout correctement et ca fini par peter.



On a rencontré le même problème chez nous, sauf qu'on tourne sans
Hibernate (Spring en solo sur une couche DAO "classique").

Du coup on a un peu plus de contrôle sur la fermeture des curseurs, et
on a pu résoudre le problème en blindant la fermeture des curseurs
explicitement (ResultSet et PreparedStatement) tout de suite après leur
utilisation, sans s'appuyer sur la cascade qu'est sensé faire le driver
(un close sur connection devrait fermer statement et resultset associés,
ce qui n'est apparemment pas toujours le cas...).

Les boucles imbriquées sont vicieuses aussi, ça ouvre vite un paquet de
curseur, on a du les refaire avec un seul curseur (en passant par des
listes) pour que ça passe. Bref, ça a été une vrai plaie et ça nous a
pris pas mal de temps, mais ça a fini par passer ... le dba n'était pas
vraiment d'accord pour augmenter le nombre de curseurs max sur la base
qu'on utilisait.

Sinon j'avais un pote qui voulait intégrer le client "lourd" d'oracle
dans un driver JDBC, faudrait que je lui demande si ça a abouti ... ^_^

Ah dernier truc, même si je ne pense pas que ça serve dans le cas
d'Hibernate : la propriété logAbandonned de DBCP est super pratique pour
"tracer" les curseurs abandonnés...

Voir sur le site de sun pour en downloader un.

J'en ai parlé avec des potes qui ont eu le même problème le fait de
passer sur un driver JDBC d'un autre fournisseur a solutionné le
problème.


C'est ou sur le site de Sun ? J'ai pas trouvé et ça m'intéresserait
beaucoup ! ;)

Simon


Avatar
Trognon Patrice
Simon OUALID wrote:


J'utilise celui trouvé sur le site d'oracle oui (ojdbc14-1.jar).



Perso j'ai aussi un projet sur Oracle ou je finis par peter en
too many cursors open, j'ai bien vérifier mon code je ferme
tout correctement et ca fini par peter.



On a rencontré le même problème chez nous, sauf qu'on tourne sans
Hibernate (Spring en solo sur une couche DAO "classique").

Du coup on a un peu plus de contrôle sur la fermeture des curseurs, et
on a pu résoudre le problème en blindant la fermeture des curseurs
explicitement (ResultSet et PreparedStatement) tout de suite après leur
utilisation, sans s'appuyer sur la cascade qu'est sensé faire le driver
(un close sur connection devrait fermer statement et resultset associés,
ce qui n'est apparemment pas toujours le cas...).

Les boucles imbriquées sont vicieuses aussi, ça ouvre vite un paquet de
curseur, on a du les refaire avec un seul curseur (en passant par des
listes) pour que ça passe. Bref, ça a été une vrai plaie et ça nous a
pris pas mal de temps, mais ça a fini par passer ... le dba n'était pas
vraiment d'accord pour augmenter le nombre de curseurs max sur la base
qu'on utilisait.

Sinon j'avais un pote qui voulait intégrer le client "lourd" d'oracle
dans un driver JDBC, faudrait que je lui demande si ça a abouti ... ^_^

Ah dernier truc, même si je ne pense pas que ça serve dans le cas
d'Hibernate : la propriété logAbandonned de DBCP est super pratique pour
"tracer" les curseurs abandonnés...

Voir sur le site de sun pour en downloader un.

J'en ai parlé avec des potes qui ont eu le même problème le fait de
passer sur un driver JDBC d'un autre fournisseur a solutionné le
problème.


C'est ou sur le site de Sun ? J'ai pas trouvé et ça m'intéresserait
beaucoup ! ;)

Simon


http://developers.sun.com/product/jdbc/drivers/index.html

voila l'url :)

c'est celui de DataDirect que je vais tester en sept.


Les boucles imbriquées sont vicieuses aussi, ça ouvre vite un paquet de
curseur, on a du les refaire avec un seul curseur (en passant par des
listes)


Tu peux expliquer ce que tu entends par l'histoire des listes, tu caches
les datas dans des lists Java c'est ca que tu veux dire ?

J'ai typequement le cas des boucles inbriquées en fait.


--
Cordialement,

Patrice Trognon
http://www.javadevel.com



Avatar
Stephane Zuckerman
Les boucles imbriquées sont vicieuses aussi, ça ouvre vite un paquet de
curseur, on a du les refaire avec un seul curseur (en passant par des
listes)


Tu peux expliquer ce que tu entends par l'histoire des listes, tu caches
les datas dans des lists Java c'est ca que tu veux dire ?

J'ai typequement le cas des boucles inbriquées en fait.
Je ne connais pas le fonctionnement de Spring, mais au moins au niveau

d'Hibernate, le fait d'utiliser une liste pour récupérer les résultats
permet de passer d'abord par le cache Hibernate, et évite ainsi certaines
requêtes (et ouvertures de curseurs)... De plus (mais là, il faudrait que
je me renseigne en regardant mieux le code d'Hibernate), il semblerait que
l'utilisation de la méthode iterate() dans la classe Query ne soit pas une
très bonne idée... Bref, il y a du boulot pour détecter d'où vient
l'erreur ... :-/

--
"Je deteste les ordinateurs : ils font toujours ce que je dis, jamais ce
que je veux !"
"The obvious mathematical breakthrough would be development of an easy
way to factor large prime numbers." (Bill Gates, The Road Ahead)


Avatar
Stephane Zuckerman
Perso j'ai aussi un projet sur Oracle ou je finis par peter en
too many cursors open, j'ai bien vérifier mon code je ferme
tout correctement et ca fini par peter.


Bon, après recherches sur le site d'Oracle, je suis tombé sur ce lien :
http://support.bea.com/application_content/product_portlets/support_patterns/wls/Investigating_JDBC_Problems_Pattern.html


J'ai donc trouvé une super solution, je vais utiliser un autre driver JDBC :))


Je crois que finalement, oui, ce sera la meilleure solution :-)

--
"Je deteste les ordinateurs : ils font toujours ce que je dis, jamais ce
que je veux !"
"The obvious mathematical breakthrough would be development of an easy
way to factor large prime numbers." (Bill Gates, The Road Ahead)

Avatar
Trognon Patrice
Stephane Zuckerman wrote:

Perso j'ai aussi un projet sur Oracle ou je finis par peter en
too many cursors open, j'ai bien vérifier mon code je ferme
tout correctement et ca fini par peter.


Bon, après recherches sur le site d'Oracle, je suis tombé sur ce lien :
http://support.bea.com/application_content/product_portlets/support_patterns/wls/Investigating_JDBC_Problems_Pattern.html


J'ai donc trouvé une super solution, je vais utiliser un autre driver
JDBC :))


Je crois que finalement, oui, ce sera la meilleure solution :-)



Ben comment le dire avec diplomatie ....
"Oracle n'a jamais été connu pour fournir un bon driver JDBC"

ca va comme ca, c'est soft ? je voudrais pas vexer mes potes de chez
oracle (lol).

--
Cordialement,

Patrice Trognon
http://www.javadevel.com


Avatar
nelsounet
J'ai donc trouvé une super solution, je vais utiliser un autre driver
JDBC :))


Je crois que finalement, oui, ce sera la meilleure solution :-)



Ben comment le dire avec diplomatie ....
"Oracle n'a jamais été connu pour fournir un bon driver JDBC"

ca va comme ca, c'est soft ? je voudrais pas vexer mes potes de chez
oracle (lol).



Et sans vexer personne, lequel conseillez-vous pour accèder à une base
Oracle 9i ?

Merci de votre réponse !

Nelson



Avatar
Trognon Patrice
nelsounet wrote:


J'ai donc trouvé une super solution, je vais utiliser un autre driver
JDBC :))


Je crois que finalement, oui, ce sera la meilleure solution :-)



Ben comment le dire avec diplomatie ....
"Oracle n'a jamais été connu pour fournir un bon driver JDBC"

ca va comme ca, c'est soft ? je voudrais pas vexer mes potes de chez
oracle (lol).



Et sans vexer personne, lequel conseillez-vous pour accèder à une base
Oracle 9i ?

Merci de votre réponse !


lol,

Je vais tester en sept celui de DataDirect si ma mémoire est bonne,
en général les retours sont bons sur ce driver.

--
Cordialement,

Patrice Trognon
http://www.javadevel.com