java.sql.SQLException: - ORA-01000: un maximum de curseurs ouverts dépassé
Je reçois un ORA-01000 exception SQL. J'ai donc quelques questions concernant il.
- Maximum de curseurs ouverts exactement du nombre de connexions JDBC, ou sont-ils liés à la déclaration et objets resultset nous avons créé pour une seule connexion ? (Nous sommes à l'aide de pool de connexions)
- Est-il un moyen de configurer le nombre de déclaration/objets resultset dans la base de données (comme des connexions) ?
- Est-il conseillé d'utiliser la variable d'instance ou déclaration d'un objet resultset au lieu de la méthode locale ou déclaration d'un objet resultset dans un seul thread de l'environnement ?
-
Fait de l'exécution d'une instruction préparée dans une boucle à l'origine de ce problème ? (Bien sûr, j'aurais pu utiliser sqlBatch) Remarque: pStmt est fermé une fois que la boucle est terminée.
{ //method try starts String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)"; pStmt = obj.getConnection().prepareStatement(sql); pStmt.setLong(1, subscriberID); for (String language : additionalLangs) { pStmt.setInt(2, Integer.parseInt(language)); pStmt.execute(); } } //method/try ends { //finally starts pStmt.close() } //finally ends
-
Ce qui va se passer si conn.createStatement() et conn.prepareStatement(sql) sont appelés plusieurs fois sur l'objet de connexion ?
Edit1:
6. L'utilisation de la Faiblesse de l'/Soft de référence de la déclaration de l'objet de l'aide dans la prévention de la fuite ?
Edit2:
1. Est-il de toute façon, je peux trouver tous les disparus "de la déclaration.close()"dans mon projet ? Je comprends ce n'est pas une fuite de mémoire. Mais j'ai besoin de trouver un énoncé de référence (d'où close() n'est pas exécutée) admissibles pour la collecte des ordures ? Un outil disponible ? Ou dois-je analyser manuellement ?
Merci de m'aider à le comprendre.
Solution
Pour trouver le curseur ouvert dans Oracle DB pour le nom d'utilisateur -VELU
Aller à ORALCE machine et de commencer à sqlplus en tant que sysdba.
[oracle@db01 ~]$ sqlplus / as sysdba
Puis exécutez
SELECT A.VALUE,
S.USERNAME,
S.SID,
S.SERIAL#
FROM V$SESSTAT A,
V$STATNAME B,
V$SESSION S
WHERE A.STATISTIC# = B.STATISTIC#
AND S.SID = A.SID
AND B.NAME = 'opened cursors current'
AND USERNAME = 'VELU';
Si possible merci de lire ma réponse à la fin.
- Vous pouvez poster votre code complet? Il serait intéressant de voir où en êtes-vous fermeture de l'ouverture des accolades ouvert pour
for (String language : additionalLangs) {
- Kanagavelu Sugumar : pourquoi ne pas poser 5 questions différentes dans?
- Voici une réponse que j'ai trouvé très utile: stackoverflow.com/a/4507507/501113
- Merci de voir si la réponse est utile : stackoverflow.com/questions/34716456/...
- Pour le suivi des curseurs ouverts dans Oracle, vous pouvez également jeter un oeil à la
SYS.V$OPEN_CURSOR
vue. Cela vous donnera non seulement le SID, mais aussi le texte SQL.
Vous devez vous connecter pour publier un commentaire.
ORA-01000, le maximum-ouvrir-les curseurs de l'erreur, est un très commune erreur dans la base de données Oracle de développement. Dans le contexte de Java, il se produit lorsque l'application tente d'ouvrir plusieurs jeux de résultats qu'il y a configuré les curseurs sur une instance de base de données.
Causes les plus courantes sont les suivantes:
Erreur de Configuration de la
Solution:
Curseur de fuite
Fond
Cette section décrit certains de la théorie derrière les curseurs et comment JDBC doit être utilisé. Si vous n'avez pas besoin de connaître l'arrière-plan, vous pouvez ignorer cela et aller directement à "Éliminer les Fuites".
Qu'est ce qu'un curseur?
Un curseur est une ressource sur la base de données que détient l'état d'une requête, plus précisément la position où un lecteur est dans un jeu de résultats. Chaque instruction SELECT a un curseur, et PL/SQL stockées procédures pouvez l'ouvrir et l'utiliser autant de curseurs comme ils le souhaitent. Vous pouvez en savoir plus sur les curseurs sur Orafaq.
Une instance de base de données sert généralement plusieurs schémas, de nombreux utilisateurs chacun avec plusieurs sessions. Pour ce faire, il dispose d'un nombre fixe de curseurs disponibles pour tous les schémas, les utilisateurs et les sessions. Lorsque tous les curseurs sont ouvertes (en utilisation) et de la demande qui nécessite un nouveau curseur, la demande échoue avec une erreur ORA-010000 erreur.
Recherche et définition du nombre de curseurs
Le nombre est normalement configuré par l'administrateur lors de l'installation. Le nombre de curseurs actuellement en cours d'utilisation, le nombre maximal et la configuration peut être consulté dans les fonctions de l'Administrateur en Oracle SQL Developer. À partir de SQL il peut être défini:
Relatives JDBC dans la JVM pour les curseurs sur la DB
JDBC objets ci-dessous sont étroitement couplée à la suite de concepts de base de données:
JDBC est thread-safe: Il est tout à fait OK pour passer les différents JDBC objets entre les threads.
Par exemple, vous pouvez créer la connexion à un fil, un autre thread peut utiliser cette connexion pour créer un PreparedStatement et un troisième fil peut traiter l'ensemble de résultats. La principale restriction est que vous ne pouvez pas avoir plus d'un jeu de résultats ouvrent sur un seul PreparedStatement à tout moment. Voir N'Oracle DB en charge plusieurs (parallèle) opérations par connexion?
Noter qu'une base de données de commettre se produit sur une Connexion, et donc tous les DML (INSERT, UPDATE et DELETE) sur que la connexion s'engager ensemble. Par conséquent, si vous souhaitez prendre en charge plusieurs opérations en même temps, vous devez avoir au moins une Connexion pour chaque Transaction simultanée.
De clôture JDBC objets
Un exemple typique de l'exécution d'un jeu de résultats est:
Notez comment la clause finally ignore tout de l'exception soulevée par le close():
Si vous avez une boucle, par exemple, la création et l'exécution des Instructions, n'oubliez pas de fermer chaque Instruction dans la boucle.
Dans Java 7, Oracle a introduit la AutoCloseable interface qui remplace la plupart de la version 6 de Java standard avec quelques belles sucre syntaxique.
Holding JDBC objets
JDBC objets peuvent être conservés de façon sécuritaire dans des variables locales, instance de l'objet et les membres de la classe. Il est généralement préférable d':
Il y a cependant une exception: Si vous utilisez des Ejb, ou un Servlet/JSP conteneur, vous devez suivre un strict modèle de thread:
Des fuites
Il y a un certain nombre de processus et d'outils pour les aider à détecter et à éliminer JDBC fuites:
Au cours du développement - la capture des bugs au début est de loin la meilleure approche:
Pratiques de développement: les Bonnes pratiques de développement devrait réduire le nombre de bugs dans votre logiciel avant qu'il ne quitte le développeur du bureau. Pratiques spécifiques comprennent:
D'Analyse de Code statique: Utiliser un outil comme l'excellent Findbugs pour effectuer une analyse de code statique. Ce ramasse beaucoup d'endroits où l'close() n'a pas été correctement traitées. Findbugs a un plugin pour Eclipse, mais il fonctionne également en mode autonome pour un compromis, a intégrations Jenkins CI et d'autres outils de construction de
Au moment de l'exécution:
Holdability et de s'engager
Journalisation au moment de l'exécution.
Vous pouvez ajouter un débogage pilote JDBC pour votre projet (pour le débogage - ne fait pas l'appliquer). Un exemple (je ne l'ai pas utilisé) est log4jdbc. Ensuite, vous devez faire une analyse simple sur ce fichier pour voir qui l'exécute ne correspond à proximité. Le comptage de l'ouvrir et ferme doit indiquer s'il existe un problème potentiel
D'autres pensées
Pouvez-vous utiliser WeakReferences à la poignée de fermeture des connexions?
Faible et mou références sont des moyens vous permettant de faire référence à un objet d'une manière qui permet à la JVM pour les ordures recueillir le point de référence à tout moment qu'il jugera bon de le faire (en supposant que il n'y a aucune référence forte chaînes à cet objet).
Si vous passez un ReferenceQueue dans le constructeur de la faiblesse ou de la faiblesse de la Référence, l'objet est placé dans le ReferenceQueue lorsque l'objet est GC ed lorsqu'il se produit (si elle a lieu). Avec cette approche, vous pouvez interagir avec l'objet de la finalisation et vous pourriez fermer ou finaliser l'objet à ce moment-là.
Fantôme références sont un peu plus étrange; leur seul but est de contrôler la finalisation, mais vous pouvez ne jamais obtenir une référence à l'objet d'origine, donc ça va être dur d'appeler la méthode close() sur elle.
Cependant, c'est rarement une bonne idée pour tenter de contrôle lors de la GC est exécuté (Faible, Doux et PhantomReferences vous laisser savoir après le fait que l'objet est mis en file d'attente pour le GC). En effet, si la quantité de mémoire de la JVM est grand (eg-Xmx2000m), vous pourriez jamais GC de l'objet, et vous aurez encore l'expérience de l'ORA-01000. Si la mémoire JVM est petite par rapport à votre programme, vous pouvez constater que le jeu de résultats et PreparedStatement objets sont GCed immédiatement après la création (avant de lire), ce qui ne sera vraisemblablement pas votre programme.
TL;DR: La faiblesse du mécanisme de référence n'est pas une bonne façon de gérer et de fermeture de l'Instruction et objets ResultSet.
resultSet.getStatement().close()
Je suis ajoutant peu plus de compréhension.
Loggin en tant que sysdba.
Dans Putty (Oracle login):
Dans SqlPlus:
Nom d'utilisateur:
sys as sysdba
Ensemble session_cached_cursors de la valeur à 0 pour qu'il l'habitude d'avoir fermé les curseurs.
Sélectionnez existant OPEN_CURSORS valeur défini par connexion en DB
Ci-dessous est la requête pour trouver le SID/liste des connexions avec le curseur ouvert valeurs.
Utiliser la requête ci-dessous pour identifier le sql dans le curseurs ouverts
Maintenant déboguer le Code et Profitez-en!!! 🙂
Corriger votre Code comme ceci:
Êtes-vous sûr que vous êtes vraiment à la fermeture de votre pStatements, les connexions et les résultats?
Pour analyser des objets ouverts, vous pouvez implment un délégataire modèle, qui encapsule le code autour de votre statemant, de connexion et d'objets de résultat. Donc, vous allez voir, si un objet a clôturé avec succès.
Un Exemple pour: pStmt = obj.getConnection().prepareStatement(sql);
Si votre application est une application Java EE en cours d'exécution sur Oracle WebLogic que le serveur d'application, une cause possible de ce problème est le Déclaration De La Taille De La Mémoire Cache configuration de WebLogic.
Si le Cache d'Instruction de réglage de la Taille pour une source de données particulière est à peu près égale, voire supérieure, la base de données Oracle maximum curseur ouvert à compter de réglage, puis tous les curseurs peuvent être consommés par les mis en cache SQL qui sont ouverts par WebLogic, résultant de l'ERO-01000 erreur.
Pour répondre à cela, réduire le Cache d'Instruction de réglage de la Taille pour chaque WebLogic source de données qui pointe vers la base de données Oracle à être beaucoup moins que le maximum de curseur comte de réglage sur la base de données.
Dans la Console d'administration WebLogic 10, le Cache d'Instruction de réglage de la Taille pour chaque source de données peut être trouvé à des Services (menu de navigation de gauche) > Sources de Données > (personne physique de la source de données) > Pool de connexions de l'onglet.
Moi aussi j'avais été confronté à ce problème.Ci-dessous l'exception habitude de venir
J'ai été en utilisant Framework Spring avec Spring JDBC pour la couche dao.
Mon application qui a servi à la fuite des curseurs en quelque sorte, et au bout de quelques minutes, Il a utilisé pour me donner cette exception.
Après beaucoup de tests pour le débogage et l'analyse, j'ai trouvé qu'il y avait le problème avec le de l'Indexation, des Contraintes Primary Key et Unique dans l'un des Table être utilisé dans le Requête j'ai été en cours d'exécution.
Ma demande a été d'essayer de mettre à jour le Colonnes qui ont été à tort Indexé.
Donc, chaque fois que ma demande a été frapper à la requête de mise à jour sur les colonnes indexées, La base de données était en train de faire la réindexation basé sur les valeurs mises à jour. Il fuyait la curseurs.
J'ai été en mesure de résoudre le problème en faisant une Bonne Indexation sur les colonnes qui ont été utilisés pour la recherche dans la requête et à l'application de contraintes à chaque fois que nécessaire.
J'ai connu le même problème (ORA-01000) aujourd'hui. J'avais une boucle for dans le try{}, pour exécuter une instruction SELECT dans une DB Oracle de nombreuses fois (en changeant à chaque fois un paramètre), et dans le finally{} j'ai eu mon code pour fermer Resultset, PreparedStatement et de la Connexion, comme d'habitude. Mais dès que j'ai atteint un montant spécifique de boucles (1000) j'ai eu l'Oracle d'erreur concernant le trop grand nombre de curseurs ouverts.
Basé sur le poteau par Andrew Alcock ci-dessus, j'ai fait des modifications de sorte que à l'intérieur de la boucle, j'ai fermé chaque jeu de résultats et de chaque instruction après l'obtention de données et avant de faire la boucle de nouveau, et qui a résolu le problème.
De plus, exactement le même problème s'est produit dans une autre boucle d'Instructions Insert, dans un autre Oracle DB (ORA-01000), cette fois, après 300 consolidés. De nouveau, il a été résolu de la même manière, donc soit l'un PreparedStatement ou le jeu de résultats ou deux, compter aussi les curseurs jusqu'à ce qu'ils sont fermés.
Avez-vous set autocommit=true? Si pas, essayez ceci:
requête pour trouver sql qui s'est ouvert.
Ce problème survient principalement lorsque vous utilisez le regroupement de connexion, car lorsque vous fermez la connexion de connexion de revenir à la connexion de la piscine et de toutes les curseur associé à cette connexion ne jamais se ferment, comme la connexion à la base de données est toujours ouverte.
Donc, une autre solution est de diminuer le régime de ralenti du temps de connexion des connexions dans la piscine, donc peut-chaque fois que la connexion est inactive dans le cadre de, disons, 10 sec , la connexion à la base de données sera fermé et nouvelle connexion créée pour mettre dans la piscine.
J'ai fait face à la même question parce que j'ai été interrogation db pour plus de 1000 itérations.
J'ai utilisé de l'essayer et, enfin, dans mon code. Mais était encore en train d'erreur.
Pour résoudre ce que je viens juste connecté à oracle db et courut au-dessous de la requête:
ALTER SYSTEM SET open_cursors = 8000 PORTÉE=DEUX;
Et cela a résolu mon problème immédiatement.
Utilisant le traitement par lots entraînera une diminution des frais généraux. Voir le lien suivant pour exemples:
http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm
Dans notre cas, nous avons été en utilisant Hibernate et nous avons eu de nombreuses variables de référencement sur le même Hibernate mappé entité. Nous avons été la création et l'enregistrement de ces références dans une boucle. Chaque référence a ouvert un curseur, et l'a gardé ouvert.
Nous avons découvert cela à l'aide d'un requête pour vérifier le nombre de curseurs ouverts lors de l'exécution de notre code, parcourant avec un débogueur et de manière sélective, en commentant les choses.
Pourquoi chaque nouvelle référence a ouvert un autre curseur - l'entité en question avait des collections d'autres entités mappées à elle et je pense que cela a quelque chose à faire avec elle (peut-être pas juste pour cette seule mais en combinaison avec la façon dont nous avons configuré le mode de lecture et les paramètres de cache). Hibernate lui-même a eu des bugs d'oublier de fermer les curseurs ouverts, mais il semblerait que ceux-ci ont été corrigés dans les versions ultérieures.
Puisque nous n'avons pas vraiment besoin d'avoir autant de dupliquer les références à la même entité de toute façon, la solution était d'arrêter de créer et de s'y accrocher toutes ces références redondantes. Une fois que nous n'avons que le problème lorsque l'écart.
J'ai eu ce problème avec ma source de données dans WildFly et Tomcat, de vous connecter à Oracle 10g.
J'ai trouvé que, sous certaines conditions, la déclaration n'était pas fermé, même lorsque la déclaration.close() a été invoquée.
Le problème était avec le Pilote Oracle, nous avons été à l'aide de: ojdbc7.jar. Ce pilote est prévu pour Oracle 12c et 11g, et il semble a quelques problèmes quand est utilisé avec Oracle 10g, donc je reviens à ojdbc5.jar et maintenant, tout fonctionne bien.