IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JDBC Java Discussion :

Oracle et problème de fermeture de resultset/statement


Sujet :

JDBC Java

  1. #1
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut Oracle et problème de fermeture de resultset/statement
    Bonjour,

    je suis un utilisateur relativement novice en JDBC et j'ai un problème que je n'arrive pas à résoudre.

    J'ai développé une application JDBC donc et j'obtiens l'erreur oracle : ORA-01000: maximum open cursors exceeded

    Après vérification de l'erreur, c'est que mon nombre de curseur ouvert est trop important.
    Je vérifie mon code, je les ferme tous de suite après utilisation.
    Par contre dans Oracle, ils apparaissent toujours comme ouverts.
    On dirait que le close est sans effet.

    Mon application étant complexe et les appels à JDBC encapsulés dans une classe de gestion des accès à la database, voici le code simple que j'ai essayé pour tester l'effet des close():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    try {
    			Class cOracleDriver;
    			Driver dOracleDriver;
    			cOracleDriver=Class.forName("oracle.jdbc.driver.OracleDriver");
    			dOracleDriver=(Driver) cOracleDriver.newInstance();
    			DriverManager.registerDriver(dOracleDriver);
    			Connection con = DriverManager.getConnection("jdbc:oracle:thin:@guzet.**.net:1521:mydb","user","mdp");
    			Statement st = con.createStatement();
    			ResultSet myRS;
    			myRS = st.executeQuery("select 1 from dual");
    			st.close();
    			myRS.close();
    			System.out.println("endormi");
    			Thread.sleep(30000);
    			System.out.println("reveillé");
    			con.close();
    			System.out.println("endormi");
    			Thread.sleep(30000);
    			System.out.println("reveillé");
    			System.out.println("fin");
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    Lors du premier sleep, le curseur est toujours ouvert dans oracle.
    Requête exécutée pour le vérifier :
    SELECT * from v$open_cursor WHERE SID = 29;
    Le numéro de SID est le bon, j'ai vérifié auparavant.

    Lors du second sleep, la connexion est bien fermée, le curseur n'apparait plus.

    J'utilise le driver fournit par Oracle et téléchargé à cette URL:
    http://www.oracle.com/technology/sof.../jdbc9201.html
    C'est la version pour Oracle 9.2.0.8 qui est la version de SGBD qu'on utilise.
    J'utilise le JDK 1.6.
    Les ordres SQL marchent bien quels qu'ils soient, j'ai juste ce problème de curseur qui restent ouverts.

    Après avoir lu les FAQ et cherché sur le net, j'ai rien trouvé pour résoudre ce problème donc si vous pouviez m'aider (même si ce ne sont que des axes de recherche !), je vous en remercie d'avance !

  2. #2
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    normalement, tous les objets ouverts doivent être fermés dans la clause finally, et ce pour être sûr de les fermer justement ...

    Est ce que ça n'améliore pas les choses ?

    [EDIT] d'ailleurs pour ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    st.close();
    myRS.close();
    c'est dans l'ordre inverse qu'il faut fermer ...
    [/EDIT]

    PS : enlève l'url de ton serveur (ou les login, mot de passe)
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

  3. #3
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    Il est certain que ton "canal" vers la base de données est issu de Connection, pas de Statement (ou PreparedStatement) ni ResultSet.
    D'ailleurs, tu peux créer plusieurs Statement sur la même connexion et obtenir autant de resultSet.
    Dans ton cas, il faudra fermer la connexion...

    Tu peux (peut-être) passer par un pool de connexions pour accélérer l'acquisition d'une connexion (si le problème vient du temps d'acquisition)

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par in Voir le message
    normalement, tous les objets ouverts doivent être fermés dans la clause finally, et ce pour être sûr de les fermer justement ...

    Est ce que ça n'améliore pas les choses ?

    PS : enlève l'url de ton serveur (ou les login, mot de passe)

    Les logins/mdp ne sont pas les bons (mais j'ai édité l'url quand même ^^)

    J'ai essayé avec un bloc try{}finally{} pour être sûr de les fermer et même résultat

    OButterlin, dans ce cas là, je ne peux pas clore les resultset ou les statements ?
    On ne peut pas avoir une connexion persistante à la BD et fermer des objets liés à cette connexion ?

    Je vais voir du coté d'un pool de connexion mais j'aimerai quand même arriver à clore mes recordset en gardant ma session ouverte. Ca me parait possible et pas illogique.

  5. #5
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    Il est tout à fait possible de garder une connexion ouverte et de l'utiliser n fois mais il faut être certain de ne pas en demander une autre sans avoir fermé la précédente...
    Et si tous tes programmes font ça, tu arriveras au nombre max de connexions ...

    Mais franchement, il vaut mieux la fermer après usage et en demander une nouvelle au début du traitement (en même temps, tu éviteras le cas où la transaction s'est fait shooter par une cause externe, timeout par exemple).

    Sinon, peux-tu expliquer un peu plus en détail ce que tu cherches à faire ?

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Pour le gestionnaire de connexion implémenté, pas de problème.
    Il ne se connecte qu'une fois à la base de donnée par session de l'outil. Donc le nombre de connexion n'excède jamais une par utilisateur.
    Le timeout est géré aussi.

    En gros je développe l'outil d'administration d'une application basée sur Oracle. Développement en Java vous l'aurez deviné.

    Sur certaines IHM, j'ai plus d'une dizaine de requêtes à lancer donc clore la connexion puis la relancer, c'est pas top niveau perfos. Surtout que là je suis sur le site mais cette appli va être déployée aux Etats Unis et les temps de connexion sont encore plus génants dans ce cas là.

    Je vais essayer en inversant l'ordre des close (d'abord resultSet puis Statement, meme si d'après la doc, un close du statement clos les resultsets associés).

    Je vais tester ma connexion en ajoutant cette commande : setHoldability (ResultSet.CLOSE_CURSORS_AT_COMMIT )
    voir si ça résoud le problème.

    Si rien ne marche, je me tournerai vers les pools de connexion ma ça m'emballe pas plus que ça pour ce que j'ai à faire...

  7. #7
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    A priori, ton problème est plutôt simple...
    Si tu as une connexion par client, créé plusieurs statements ça fonctionnera sans problème...
    N'oublie pas de fermer le statement à la fin de ta méthode quand même...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    Statement stmt1 = null;
    PreparedStatement pstmt2 = null;
     
    try
    {
       stmt1 = connection.createStatement();
       pstmt2 = connection.prepareStatement("select * from Table2 where idParent=?");
     
       ResultSet rs1 = stmt1.executeQuery("select * from Table1");
       while ( rs1.next() )
       {
          pstmt2.setInt(1, rs.getInt("ID"));
          ResultSet rs2 = pstmt2.executeQuery();
          while ( rs2.next() )
          {
             ...
          }
       }
    }
    catch (Exception e)
    {
       ...
    }
    finally
    {
       if ( stmt1 != null ) stmt1.close();
       if ( pstmt2 != null ) pstmt2.close();
    }
    Ce genre de chose fonctionne très bien...

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Ben justement, non.
    Si tu regardes mon exemple très simple, le statement utilisé est fermé mais le curseur Oracle est toujours ouvert.

    Après recherches, le CLOSE_CURSORS_AT_COMMIT n'est pas supporté par le driver Oracle JDBC.
    Donc je vais tester les performances en ouvrant/fermant la connexion à chaque fois et on verra bien.
    Si les perfos ne sont pas bonnes, j'ouvrirai un ticket metalink et je vous tiendrai au courant.

  9. #9
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    C'est curieux, j'utilise une base Oracle 10 et je n'ai pas de problème.
    Il y a peut-être une erreur dans ton code, peux-tu le montrer (du moins un morceau significatif) ?

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    je parle du code posté lors de mon premier post.
    Le plus simple possible.

  11. #11
    Nouveau membre du Club
    Inscrit en
    Août 2007
    Messages
    23
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Août 2007
    Messages : 23
    Points : 31
    Points
    31
    Par défaut
    Le probleme ne vient pas necessairement de ton code.
    Je ne connais pas l'utilisation de ta BDD mais pour ma part, j'ai deja eu ce probleme et c'etait un autre programme qui saturait oracle et j'obtenais la meme erreur. Checke sur oracle qui se connecte et aussi les param oracle car sur certaine conf il ne ferme jamais un curseur ouvert.

  12. #12
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par lasticot69 Voir le message
    je parle du code posté lors de mon premier post.
    Le plus simple possible.
    Ca je sais, mais ce code là ne risque pas de garder la connexion active une fois le con.close() executé, donc, tu dois bien avoir un autre programme qui déconne... ou peut-être comme le suggère Trencavel un paramétrage spécial...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par Trencavel Voir le message
    Le probleme ne vient pas necessairement de ton code.
    Je ne connais pas l'utilisation de ta BDD mais pour ma part, j'ai deja eu ce probleme et c'etait un autre programme qui saturait oracle et j'obtenais la meme erreur. Checke sur oracle qui se connecte et aussi les param oracle car sur certaine conf il ne ferme jamais un curseur ouvert.
    Comme dit dans mon premier post, j'ai vérifié dans la vue v$session le SID de mon programme. Et ensuite dans la vue v$open_cursor j'ai bien vu que les curseurs ouverts l'étaient par la session correspondant au SID de mon appli.
    Je vais contacter mon admin Oracle pour voir les paramètres de la base.


    Citation Envoyé par OButterlin Voir le message
    Ca je sais, mais ce code là ne risque pas de garder la connexion active une fois le con.close() executé, donc, tu dois bien avoir un autre programme qui déconne... ou peut-être comme le suggère Trencavel un paramétrage spécial...
    Ben justement si, le programme aussi simple soit il provoque ce comportement.

    Lors du premier sleep, le resultset et le statement ont reçu l'instruction close (), la connexion non.
    Quand le programme bloque sur le premier sleep, si je regarde dans Oracle, un curseur contenant la requête qu'exécute mon programme est ouvert et son SID correspond à celui de mon programme.
    D'un point de vue Java, c'est clos, sur Oracle, non.

    Lors du second sleep, la connexion est close, tout va bien dans Oracle.

    Mon problème n'est pas de garder une connexion active mais c'est de réussir à clore des curseurs en gardant la connexion active. Chose que même le programme simple n'arrive pas à faire.

    Est ce que tu utilises le driver thin pour accéder à ta base Oracle 10g?
    Quels autres types de driver sont dispos ?
    Y a t'il mieux que le driver made in Oracle ?

    Merci encore pour votre participation

  14. #14
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    J'utilise le driver de la 10 (ojdbc14.jar).

    Mais je le répète, le comportement que tu déplores est normal.
    C'est la connexion qui représente ton canal vers oracle, tant que la connexion n'est pas fermée, il est normal que oracle la garde active, tu pourras utiliser un autre driver, le comportement sera le même.
    Le statement s'appuie sur la connexion pour être exécuté, c'est tout.

    (en comparaison simpliste, la connexion serait la route, le statement un véhicule, et tu peux en avoir un certain nombre sur la même route)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Donc à quoi sert de clore un statement si celui ci reste ouvert dans oracle ?

    Donc je vais reprendre avec ton exemple simple, je pense qu'on se comprend pas bien

    Connexion = session oracle = route.
    Statement (ou resultset associé) = curseur oracle = vehicule.

    Une fois qu'on clos un statement, la connexion reste ouverte.
    Donc la session oracle reste ouverte et le curseur oracle devrait être fermé.

    Là ce qui se passe, le curseur oracle reste ouvert. Le close est sans effet d'un point de vue oracle.

    Donc en suivant ton example, je prend mon véhicule, je vais sur la route pour conduire (exécuter ma requete et utiliser le résultat). Et quand je suis arrivé, je reste garé sur la route (curseur encore ouvert sur la connexion).

    Moi je veux pas casser la route mais juste bien garer véhicule quand j'ai fini pour laisser la place aux autres sans gros embouteillages


    Donc si tu vois pas mon problème, peux tu répondre à la question suivante:
    A quoi sert de fermer ton statement sans fermer ta session ?

  16. #16
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    Pourquoi fermer un statement :
    - pour libérer les ressources liées (comme un resultSet par exemple)
    - pour en créer un autre (pour les PreparedStatement surtout ou pour des cas spécifiques de statement ResultSet.TYPE_SCROLL_SENSITIVE etc)
    - parce que le nombre de statement lié à une connexion est limité

    Pourquoi garder un statement ouvert :
    - pour exécuter plusieurs requête consécutives rapidement (pour economiser le temps d'acquisition d'un statement) mais sans imbrication des requêtes

    Mais ça ne devrait pas excéder un cycle de traitement...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  17. #17
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Pourquoi fermer un statement :
    - pour libérer les ressources liées (comme un resultSet par exemple)
    - pour en créer un autre (pour les PreparedStatement surtout ou pour des cas spécifiques de statement ResultSet.TYPE_SCROLL_SENSITIVE etc)
    - parce que le nombre de statement lié à une connexion est limité

    Pourquoi garder un statement ouvert :
    - pour exécuter plusieurs requête consécutives rapidement (pour economiser le temps d'acquisition d'un statement) mais sans imbrication des requêtes

    Mais ça ne devrait pas excéder un cycle de traitement...
    Donc tu es d'accord avec moi que si tu fermes un statement mais que les objets oracles ne sont pas fermés en database c'est qu'il y a un problème ?

    Car dans ce que je te dis, si je ferme un statement en laissant la connexion oracle ouverte, le nombre de statement lié à la connexion ne diminue pas. Le close n'a aucun effet.

    On est enfin d'accord sur le problème ?

  18. #18
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 311
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 311
    Points : 9 524
    Points
    9 524
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par lasticot69 Voir le message
    On est enfin d'accord sur le problème ?
    Comme quoi, tout arrive
    C'est très probablement un paramètre oracle qui provoque ça, mais lequel, je n'en sait pas trop...
    Il semble qu'oracle est une notion "d'implicit caching" sur les statements
    http://download-uk.oracle.com/docs/c...c2.htm#1075262

    Je te laisse consulter la doc...

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  19. #19
    Candidat au Club
    Inscrit en
    Janvier 2005
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 16
    Points : 4
    Points
    4
    Par défaut
    Merci pour ton aide mais l'implicit caching ne marche que pour les prepared et callable statement.
    Dans mon cas, il faudrait que je trouve pour tout type de statement.

    J'ai parcouru vite fait la doc oracle encore une fois, j'ai rien trouvé de plus.

    Je contacte mon DBA dès que possible et je vous tiens au couant au cas où ça interresse quelqu'un.

  20. #20
    Membre habitué Avatar de adil_vpb
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 326
    Points : 132
    Points
    132
    Par défaut
    Citation Envoyé par lasticot69 Voir le message
    Donc à quoi sert de clore un statement si celui ci reste ouvert dans oracle ?

    Donc si tu vois pas mon problème, peux tu répondre à la question suivante:
    A quoi sert de fermer ton statement sans fermer ta session ?
    Bonjour,
    moi aussi j'ai le même probléme !
    Bref, je ferme mes statements, mais sur la BDD Oracle, et surtout sur OEM -> Instance -> Sessions : le programme "JDBC Thin Client" s'ajoute aux sessions à chaque fois que je rafraichi ma page !

    Et le plus délicat, c'est que j'ai des pages web qui se rafraichissent automatiquement toutes les 3 minutes par exemple !

    En plus, j'ai laissé cette page pendant une durée x minute, j'ai obtenu aprés l'erreur suivante :
    maximum number of processus (150) exceeded !

    Donc j'ai pensé de travailler avec les Pool de connexion, mais je pense pas que ca va résoudre le probléme !

    Si vous pouviez nous aidé pour trouver une solution, je vous serais reconnaissant !!!

    Merci d'avance.
    On est là pour partager notre savoir-faire !

Discussions similaires

  1. JBuilder 2005 et Oracle 9i-> Problème JDBC drive
    Par Devil666 dans le forum JBuilder
    Réponses: 1
    Dernier message: 04/04/2005, 14h14
  2. [TQuery] problème de fermeture
    Par mammistegon dans le forum Bases de données
    Réponses: 5
    Dernier message: 29/01/2005, 18h15
  3. [Thread][socket]Problème de fermeture d'un thread
    Par meda dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 04/11/2004, 01h03
  4. Problème de fermeture de l'application
    Par SkyDev dans le forum Langage
    Réponses: 2
    Dernier message: 16/06/2004, 02h06
  5. Problème de fermeture de balise <tr>
    Par nuage dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 18/03/2004, 09h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo