web-dev-qa-db-de.com

java.sql.SQLException: - ORA-01000: Maximale Anzahl offener Cursor überschritten

Ich erhalte eine ORA-01000-SQL-Ausnahme. Ich habe also einige Fragen dazu.

  1. Beziehen sich maximal geöffnete Cursor genau auf die Anzahl der JDBC-Verbindungen oder auch auf die Anweisungs- und Resultset-Objekte, die wir für eine einzelne Verbindung erstellt haben? (Wir verwenden einen Pool von Verbindungen)
  2. Gibt es eine Möglichkeit, die Anzahl der Statement/Resultset-Objekte in der Datenbank (wie Verbindungen) zu konfigurieren?
  3. Ist es ratsam, das Statement/Resultset-Objekt der Instanzvariablen anstelle des lokalen Statements/Resultset-Objekts der Methode in einer Umgebung mit einem einzigen Thread zu verwenden?
  4. Führt die Ausführung einer vorbereiteten Anweisung in einer Schleife zu diesem Problem? (Natürlich hätte ich sqlBatch verwenden können) Hinweis: pStmt wird geschlossen, sobald die Schleife beendet ist.

    { //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 
    
  5. Was passiert, wenn conn.createStatement () und conn.prepareStatement (sql) für ein einzelnes Verbindungsobjekt mehrmals aufgerufen werden?

Edit1:  6. Hilft die Verwendung des Referenzobjekts "Weak/Soft", um das Auslaufen zu verhindern? 

Edit2:  1. Gibt es eine Möglichkeit, alle fehlenden "statement.close ()" in meinem Projekt zu finden? Ich verstehe, dass es kein Speicherleck ist. Aber ich muss eine Anweisungsreferenz finden (wo close () nicht ausgeführt wird), die für die Müllsammlung geeignet ist. Irgendein Werkzeug verfügbar? Oder muss ich es manuell analysieren?

Bitte hilf mir, es zu verstehen.

Lösung

So suchen Sie den geöffneten Cursor in Oracle DB für Benutzername -VELU

Gehen Sie zur ORALCE-Maschine und starten Sie sqlplus als sysdba.

[[email protected] ~]$ sqlplus / as sysdba 

Dann renne

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';

Bitte lesen Sie meine Antwort am Ende.

100

ORA-01000, der Fehler "Maximum-Open-Cursors", ist ein äußerst häufiger Fehler in der Oracle-Datenbankentwicklung. Im Kontext von Java geschieht dies, wenn die Anwendung versucht, mehr ResultSets zu öffnen, als konfigurierte Cursor auf einer Datenbankinstanz vorhanden sind.

Häufige Ursachen sind:

  1. Konfigurationsfehler

    • Ihre Anwendung enthält mehr Threads, die die Datenbank abfragen, als Cursor auf der Datenbank. In einem Fall haben Sie eine Verbindung und einen Thread-Pool, die größer sind als die Anzahl der Cursor in der Datenbank.
    • Sie haben viele Entwickler oder Anwendungen mit derselben DB-Instanz verbunden (die wahrscheinlich viele Schemata enthalten wird), und zusammen verwenden Sie zu viele Verbindungen.
    • Lösung:

  2. Cursor undicht

    • Die Anwendung schließt ResultSets (in JDBC) oder Cursor (in gespeicherten Prozeduren in der Datenbank) nicht
    • Lösung : Cursorlecks sind Fehler; Wenn Sie die Anzahl der Cursor in der Datenbank erhöhen, wird der unvermeidliche Fehler nur verzögert. Lecks können mithilfe von statische Codeanalyse , JDBC oder Protokollierung auf Anwendungsebene und Datenbanküberwachung festgestellt werden.

Hintergrund

In diesem Abschnitt werden einige der Cursortheorien und die Verwendung von JDBC beschrieben. Wenn Sie den Hintergrund nicht kennen müssen, können Sie diesen überspringen und direkt zu "Lecks beseitigen" wechseln.

Was ist ein Cursor?

Ein Cursor ist eine Ressource in der Datenbank, die den Status einer Abfrage enthält, insbesondere die Position, an der sich ein Leser in einem ResultSet befindet. Jede SELECT-Anweisung hat einen Cursor, und gespeicherte PL/SQL-Prozeduren können so viele Cursor öffnen und verwenden, wie sie benötigen. Weitere Informationen zu Cursorn finden Sie unter Orafaq .

Eine Datenbankinstanz bedient normalerweise mehrere verschiedene Schemata und viele verschiedene Benutzer mit jeweils mehreren Sitzungen . Zu diesem Zweck steht eine feste Anzahl von Cursorn für alle Schemas, Benutzer und Sitzungen zur Verfügung. Wenn alle Cursor geöffnet sind (verwendet werden) und eine Anforderung eingeht, für die ein neuer Cursor erforderlich ist, schlägt die Anforderung mit einem ORA-010000-Fehler fehl.

Finden und Einstellen der Anzahl der Cursor

Die Nummer wird normalerweise vom DBA bei der Installation konfiguriert. Auf die Anzahl der aktuell verwendeten Cursor, die maximale Anzahl und die Konfiguration kann in den Administratorfunktionen in Oracle SQL Developer zugegriffen werden. In SQL kann eingestellt werden mit:

ALTER SYSTEM SET OPEN_CURSORS=1337 SID='*' SCOPE=BOTH;

JDBC in der JVM mit Cursorn in der DB verknüpfen

Die folgenden JDBC-Objekte sind eng an die folgenden Datenbankkonzepte gekoppelt:

  • JDBC Connection ist die Clientdarstellung einer Datenbanksitzung und stellt Datenbanktransaktionen bereit. Bei einer Verbindung kann immer nur eine Transaktion geöffnet sein (Transaktionen können jedoch verschachtelt sein).
  • Ein JDBC ResultSet wird von einem einzelnen Cursor in der Datenbank unterstützt. Wenn close () im ResultSet aufgerufen wird, wird der Cursor losgelassen.
  • Ein JDBC CallableStatement ruft eine gespeicherte Prozedur in der Datenbank auf, die häufig in PL/SQL geschrieben wird. Die gespeicherte Prozedur kann null oder mehr Cursor erstellen und einen Cursor als JDBC-ResultSet zurückgeben.

JDBC ist threadsicher: Es ist in Ordnung, die verschiedenen JDBC-Objekte zwischen Threads zu übergeben.

Beispielsweise können Sie die Verbindung in einem Thread erstellen. Ein anderer Thread kann diese Verbindung verwenden, um ein PreparedStatement zu erstellen, und ein dritter Thread kann die Ergebnismenge verarbeiten. Die einzige wichtige Einschränkung besteht darin, dass auf einem einzelnen PreparedStatement nicht mehr als ein ResultSet geöffnet sein darf. Siehe nterstützt Oracle DB mehrere (parallele) Operationen pro Verbindung?

Beachten Sie, dass ein Datenbank-Commit für eine Verbindung erfolgt und daher alle DML-Dateien (INSERT, UPDATE und DELETE) für diese Verbindung zusammen festgeschrieben werden. Wenn Sie also mehrere Transaktionen gleichzeitig unterstützen möchten, müssen Sie für jede gleichzeitige Transaktion mindestens eine Verbindung haben.

JDBC-Objekte schließen

Ein typisches Beispiel für die Ausführung eines ResultSet ist:

Statement stmt = conn.createStatement();
try {
    ResultSet rs = stmt.executeQuery( "SELECT FULL_NAME FROM EMP" );
    try {
        while ( rs.next() ) {
            System.out.println( "Name: " + rs.getString("FULL_NAME") );
        }
    } finally {
        try { rs.close(); } catch (Exception ignore) { }
    }
} finally {
    try { stmt.close(); } catch (Exception ignore) { }
}

Beachten Sie, wie die finally-Klausel alle durch close () ausgelösten Ausnahmen ignoriert:

  • Wenn Sie das ResultSet einfach ohne den try {} catch {} schließen, schlägt dies möglicherweise fehl und verhindert, dass die Anweisung geschlossen wird
  • Wir möchten zulassen, dass alle Ausnahmen, die im Hauptteil des Versuchs ausgelöst werden, an den Aufrufer weitergegeben werden. Denken Sie daran, jede Anweisung innerhalb der Schleife zu schließen, wenn Sie beispielsweise eine Schleife zum Erstellen und Ausführen von Anweisungen haben.

In Java 7 hat Oracle die AutoCloseable-Schnittstelle eingeführt, die den größten Teil des Java 6-Boilerplates durch etwas syntaktischen Zucker aus Nizza ersetzt.

Halten von JDBC-Objekten

JDBC-Objekte können sicher in lokalen Variablen, Objektinstanzen und Klassenmitgliedern gespeichert werden. Es ist im Allgemeinen besser, Folgendes zu tun:

  • Verwenden Sie Objektinstanz- oder Klassenmitglieder, um JDBC-Objekte zu speichern, die über einen längeren Zeitraum mehrfach wiederverwendet werden, z. B. Connections und PreparedStatements
  • Verwenden Sie lokale Variablen für ResultSets, da diese abgerufen, durchlaufen und dann normalerweise im Rahmen einer einzelnen Funktion geschlossen werden.

Es gibt jedoch eine Ausnahme: Wenn Sie EJBs oder einen Servlet/JSP-Container verwenden, müssen Sie ein striktes Threading-Modell befolgen:

  • Nur der Application Server erstellt Threads (mit denen er eingehende Anfragen bearbeitet)
  • Nur der Anwendungsserver erstellt Verbindungen (die Sie aus dem Verbindungspool erhalten)
  • Wenn Sie Werte (Status) zwischen Aufrufen speichern, müssen Sie sehr vorsichtig sein. Speichern Sie niemals Werte in Ihren eigenen Caches oder statischen Elementen. Dies ist in Clustern und unter anderen komischen Bedingungen nicht sicher, und der Anwendungsserver kann Ihre Daten schrecklich beschädigen. Verwenden Sie stattdessen Stateful Beans oder eine Datenbank.
  • Insbesondere halten niemals JDBC-Objekte (Connections, ResultSets, PreparedStatements usw.) über verschiedene Remote-Aufrufe - lassen Sie dies vom Anwendungsserver verwalten. Der Anwendungsserver stellt nicht nur einen Verbindungspool bereit, sondern speichert auch Ihre PreparedStatements im Cache.

Leckagen beseitigen

Es stehen eine Reihe von Prozessen und Tools zur Verfügung, mit denen JDBC-Lecks erkannt und beseitigt werden können:

  1. Während der Entwicklung ist es bei weitem am besten, Fehler frühzeitig zu erkennen:

    1. Entwicklungspraktiken: Gute Entwicklungspraktiken sollten die Anzahl der Fehler in Ihrer Software verringern, bevor diese den Entwickler-Schreibtisch verlässt. Spezifische Praktiken umfassen:

      1. Paarprogrammierung , um diejenigen ohne ausreichende Erfahrung zu unterrichten
      2. Code Bewertungen weil viele Augen besser als eins sind
      3. Komponententest Dies bedeutet, dass Sie Ihre gesamte Codebasis mit einem Testwerkzeug testen können, das die Reproduktion von Lecks trivial macht
      4. Verwenden Sie vorhandene Bibliotheken , um Verbindungen zusammenzulegen, anstatt Ihre eigenen zu erstellen
    2. Statische Code-Analyse: Verwenden Sie ein Tool wie das ausgezeichnete Findbugs , um eine statische Code-Analyse durchzuführen. Dies greift viele Stellen auf, an denen close () nicht korrekt behandelt wurde. Findbugs hat ein Plugin für Eclipse, läuft aber auch als Einzelplatzversion und ist in Jenkins CI und andere Build-Tools integriert

  2. Zur Laufzeit:

    1. Haltbarkeit und Commit

      1. Wenn die Haltbarkeit von ResultSet ResultSet.CLOSE_CURSORS_OVER_COMMIT ist, wird ResultSet geschlossen, wenn die Methode Connection.commit () aufgerufen wird. Dies kann mithilfe von Connection.setHoldability () oder mithilfe der überladenen Connection.createStatement () -Methode festgelegt werden.
    2. Protokollierung zur Laufzeit.

      1. Fügen Sie gute Protokollanweisungen in Ihren Code ein. Diese sollten klar und verständlich sein, damit der Kunde, die Supportmitarbeiter und die Teammitglieder ohne Schulung verstehen können. Sie sollten knapp sein und das Drucken der Status-/internen Werte von Schlüsselvariablen und Attributen einschließen, damit Sie die Verarbeitungslogik verfolgen können. Eine gute Protokollierung ist für das Debuggen von Anwendungen von grundlegender Bedeutung, insbesondere von Anwendungen, die bereitgestellt wurden.
      2. Sie können Ihrem Projekt einen Debugging-JDBC-Treiber hinzufügen (zum Debuggen - stellen Sie ihn nicht tatsächlich bereit). Ein Beispiel (ich habe es nicht verwendet) ist log4jdbc . Sie müssen dann einige einfache Analysen für diese Datei durchführen, um festzustellen, welche Ausführungen keinen entsprechenden Abschluss haben. Das Zählen von Öffnen und Schließen sollte aufzeigen, ob ein potenzielles Problem vorliegt

        1. Datenbank überwachen. Überwachen Sie Ihre ausgeführte Anwendung mit Tools wie der SQL Developer-Funktion "SQL überwachen" oder Quest's TOAD . Die Überwachung wird in dieser Artikel beschrieben. Während der Überwachung fragen Sie die offenen Cursor (z. B. aus Tabelle v $ sesstat) ab und überprüfen deren SQL. Wenn die Anzahl der Cursor zunimmt und (am wichtigsten) von einer identischen SQL-Anweisung dominiert wird, wissen Sie, dass Sie ein Leck mit dieser SQL haben. Suchen Sie Ihren Code und überprüfen Sie.

Andere Gedanken

Können Sie mit WeakReferences Verbindungen schließen?

Mit schwachen und weichen Referenzen können Sie ein Objekt auf eine Weise referenzieren, die es der JVM ermöglicht, den Referenten zu jedem Zeitpunkt, den sie für geeignet hält, mit Garbage zu sammeln (vorausgesetzt, es gibt keine starken Referenzketten zu diesem Objekt).

Wenn Sie eine ReferenceQueue im Konstruktor an die weiche oder schwache Referenz übergeben, wird das Objekt in die ReferenceQueue eingefügt, wenn das Objekt zum Zeitpunkt seines Auftretens GC-geprüft wird (falls überhaupt). Mit diesem Ansatz können Sie mit der Finalisierung des Objekts interagieren und das Objekt in diesem Moment schließen oder finalisieren.

Phantomreferenzen sind etwas seltsamer. Ihr Zweck ist nur, die Finalisierung zu steuern. Sie können jedoch niemals einen Verweis auf das ursprüngliche Objekt erhalten. Daher wird es schwierig sein, die Methode close () für dieses Objekt aufzurufen.

Es ist jedoch selten eine gute Idee, zu versuchen, zu steuern, wann der GC ausgeführt wird (Weak, Soft und PhantomReferences lassen Sie wissen , nachdem , dass sich das Objekt in der Warteschlange für den GC befindet). Wenn die Speicherkapazität in der JVM groß ist (z. B. -Xmx2000m), können Sie das Objekt möglicherweise nie GC, und der ORA-01000 tritt weiterhin auf. Wenn der JVM-Speicher im Verhältnis zu den Anforderungen Ihres Programms klein ist, stellen Sie möglicherweise fest, dass die Objekte ResultSet und PreparedStatement unmittelbar nach der Erstellung (bevor Sie daraus lesen können) gecodet werden, was wahrscheinlich zu einem Fehlschlagen Ihres Programms führt.

TL; DR: Der schwache Referenzmechanismus ist keine gute Methode zum Verwalten und Schließen von Statement- und ResultSet-Objekten.

276
Andrew Alcock

Ich füge noch ein wenig mehr Verständnis hinzu.

  1. Bei dem Cursor handelt es sich nur um ein Anweisungsobjekt. Es ist weder resultSet noch das Verbindungsobjekt. 
  2. Trotzdem müssen wir das Resultset schließen, um Oracle-Speicher freizugeben. Wenn Sie das Resultset jedoch nicht schließen, wird es nicht für CURSORS gezählt. 
  3. Das Closing Statement-Objekt schließt das Resultset-Objekt automatisch. 
  4. Der Cursor wird für alle Anweisungen SELECT/INSERT/UPDATE/DELETE erstellt. 
  5. Jede Oracle DB-Instanz kann mithilfe von Oracle SID identifiziert werden. In ähnlicher Weise kann Oracle DB jede Verbindung mithilfe der Verbindungs-SID identifizieren. Beide SID sind unterschiedlich. 
  6. Die Oracle-Sitzung ist also nichts anderes als eine jdbc (tcp) -Verbindung. das ist nichts als eine SID. 
  7. Wenn wir als maximale Cursor 500 festlegen, gilt dies nur für eine JDBC-Sitzung/Verbindung/SID. 
  8. Wir können also viele JDBC-Verbindungen mit der jeweiligen Anzahl von Cursor (Anweisungen) haben.
  9. Wenn die JVM beendet ist, werden alle Verbindungen/Cursor geschlossen. OR JDBCConnection wird geschlossen. CURSORS in Bezug auf diese Verbindung wird geschlossen. 

Melden Sie sich als sysdba an. 

In PuTTY (Oracle-Login):

  [[email protected] ~]$ sqlplus / as sysdba

In SqlPlus:

Benutzername: sys as sysdba

Setzen Sie den Wert für session_cached_cursors auf 0, damit der Cursor nicht geschlossen ist.

 alter session set session_cached_cursors=0
 select * from V$PARAMETER where name='session_cached_cursors'

Wählen Sie den vorhandenen OPEN_CURSORS-Wertesatz pro Verbindung in der DB aus

 SELECT max(a.value) as highest_open_cur, p.value as max_open_cur FROM v$sesstat a, v$statname b, v$parameter p WHERE a.statistic# = b.statistic# AND b.name = 'opened cursors current' AND p.name= 'open_cursors'  GROUP BY p.value;

Im Folgenden finden Sie die Abfrage, um die SID-/Verbindungsliste mit geöffneten Cursorwerten zu finden.

 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 = 'SCHEMA_NAME_IN_CAPS'

Verwenden Sie die folgende Abfrage, um die SQL-Werte in den geöffneten Cursors zu identifizieren

 SELECT oc.sql_text, s.sid 
 FROM v$open_cursor oc, v$session s
 WHERE OC.sid = S.sid
 AND s.sid=1604
 AND OC.USER_NAME ='SCHEMA_NAME_IN_CAPS'

Jetzt debuggen Sie den Code und genießen Sie es !!! :)

24

Korrigieren Sie Ihren Code wie folgt:

try
{ //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
{ //finally starts
   pStmt.close()
} 

Sind Sie sicher, dass Sie Ihre pStatements, Verbindungen und Ergebnisse wirklich schließen?

Um offene Objekte zu analysieren, können Sie ein Delegator-Muster implementieren, das Code um Statemant-, Verbindungs- und Ergebnis-Objekte bindet. Sie sehen also, ob ein Objekt erfolgreich geschlossen wird.

Ein Beispiel für: pStmt = obj. getConnection (). PrepareStatement (sql);

    class obj{ 

    public Connection getConnection(){
    return new ConnectionDelegator(...here create your connection object and put it into ...);

    } 
}


class ConnectionDelegator implements Connection{
    Connection delegates;

    public ConnectionDelegator(Connection con){
       this.delegates = con;
    }

    public Statement prepareStatement(String sql){
        return delegates.prepareStatement(sql);
    }

    public void close(){
        try{
           delegates.close();
        }finally{
           log.debug(delegates.toString() + " was closed");
        }
    }
}
4
Mirko

Wenn es sich bei Ihrer Anwendung um eine Java EE-Anwendung handelt, die auf Oracle WebLogic als Anwendungsserver ausgeführt wird, kann dies durch die Einstellung Statement Cache Size in WebLogic verursacht werden.

Wenn die Einstellung für die Größe des Anweisungscaches für eine bestimmte Datenquelle mindestens der Einstellung für die maximale Anzahl der geöffneten Cursor in der Oracle-Datenbank entspricht oder größer ist, können alle geöffneten Cursor von zwischengespeicherten SQL-Anweisungen verwendet werden, die von WebLogic offen gehalten werden im ORA-01000-Fehler.

Um dies zu beheben, reduzieren Sie die Einstellung für die Statement-Cache-Größe für jede WebLogic-Datenquelle, die auf die Oracle-Datenbank verweist, auf deutlich weniger als die Einstellung für die maximale Cursoranzahl in der Datenbank.

In der WebLogic 10 Admin Console finden Sie die Einstellung Statement Cache Size für jede Datenquelle unter Dienste (linke Navigation)> Datenquellen> (einzelne Datenquelle)> Registerkarte Verbindungspool.

3
Jon Schneider

Ich hatte heute das gleiche Problem (ORA-01000). Ich hatte eine for-Schleife in try {}, um eine SELECT-Anweisung in einer Oracle-Datenbank mehrmals auszuführen (jedes Mal, wenn ein Parameter geändert wurde), und in der letzten {} hatte ich meinen Code, um Resultset, PreparedStatement und Connection wie gewöhnlich zu schließen . Sobald ich jedoch eine bestimmte Anzahl von Schleifen (1000) erreicht hatte, bekam ich den Oracle-Fehler über zu viele offene Cursor.

Basierend auf dem Beitrag von Andrew Alcock oben habe ich Änderungen vorgenommen, so dass inside the loop, jedes Resultset und jede Anweisung nach dem Abrufen der Daten und vor dem erneuten Durchlaufen der Schleife geschlossen wurde. Dadurch wurde das Problem gelöst.

Das gleiche Problem trat außerdem in einer anderen Schleife von Insert-Anweisungen in einer anderen Oracle-Datenbank (ORA-01000) auf, diesmal nach 300 Anweisungen. Wieder wurde es auf dieselbe Weise gelöst, sodass entweder das PreparedStatement oder das ResultSet oder beide als offene Cursor gelten, bis sie geschlossen werden.

2
Kinnison84

abfrage, um die geöffnete SQL zu finden.

SELECT s.machine, oc.user_name, oc.sql_text, count(1) 
FROM v$open_cursor oc, v$session s
WHERE oc.sid = s.sid
and S.USERNAME='XXXX'
GROUP BY user_name, sql_text, machine
HAVING COUNT(1) > 2
ORDER BY count(1) DESC
1
Hlex

Auch ich war mit diesem Problem konfrontiert. Die folgende Ausnahme kam

Java.sql.SQLException: - ORA-01000: maximum open cursors exceeded

Ich habe Spring Framework mit Spring JDBC für Dao-Layer verwendet.

Meine Anwendung hat irgendwann Cursors durchgesickert und nach ein paar Minuten gab es diese Ausnahme.

Nach gründlichem Debugging und Analyse stellte ich fest, dass es ein Problem mit dem Indexing, Primary Key und Unique Constraints in einer der Table gab, das in der Query i ausgeführt wurde .

Meine Anwendung hat versucht, die Spalten zu aktualisieren, die fälschlicherweise Indexed waren ..__ Wenn also meine Anwendung die Aktualisierungsabfrage für die indizierten Spalten traf, versuchte die Datenbank die Neuindizierung auf der Grundlage der aktualisierte Werte. Es liefen die Cursor .

Ich konnte das Problem lösen, indem ich für die Spalten, die zum Durchsuchen in der Abfrage verwendet wurden, die richtige Indexierung durchführte und gegebenenfalls geeignete Einschränkungen anwendete.

1
Piyush Verma

Haben Sie autocommit = true gesetzt? Wenn nicht, probiere es aus: 

{ //method try starts  
    String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
    Connection conn = obj.getConnection()
    pStmt = conn.prepareStatement(sql);

    for (String language : additionalLangs) {
        pStmt.setLong(1, subscriberID);
        pStmt.setInt(2, Integer.parseInt(language));
        pStmt.execute();
        conn.commit();
    }
} //method/try ends { 
    //finally starts
    pStmt.close()
} //finally ends 
1
paweloque

In unserem Fall verwendeten wir Hibernate und hatten viele Variablen, die auf dieselbe zugeordnete Hibernate-Entität verweisen. Wir haben diese Referenzen in einer Schleife erstellt und gespeichert. Jede Referenz öffnete einen Cursor und hielt ihn offen.

Wir entdeckten dies, indem wir mithilfe einer -Query die Anzahl der geöffneten Cursor überprüften, während wir unseren Code liefen, mit einem Debugger schrittweise vorgehen und die Dinge selektiv kommentieren.

Warum jede neue Referenz einen anderen Cursor geöffnet hat - der betreffenden Entität waren Sammlungen anderer Entitäten zugeordnet, und ich denke, das hatte etwas damit zu tun (vielleicht nicht nur allein, sondern in Kombination mit der Konfiguration des Abrufmodus und Cache-Einstellungen). Hibernate selbst hatte bugs um nicht geschlossene Cursor geschlossen, obwohl es so aussieht, als ob diese in späteren Versionen behoben wurden.

Da wir ohnehin nicht so viele doppelte Verweise auf dieselbe Entität brauchten, bestand die Lösung darin, das Erstellen und Verwalten all dieser redundanten Verweise zu beenden. Einmal haben wir das Problem gemacht, wenn wir weg waren.

0
dshiga

Ich hatte dieses Problem mit meiner Datenquelle in WildFly und Tomcat, wenn eine Verbindung zu einem Oracle 10g hergestellt wurde.

Ich habe festgestellt, dass die Anweisung unter bestimmten Bedingungen nicht geschlossen wurde, auch wenn die Anweisung statement.close () aufgerufen wurde .. Das Problem war mit dem von uns verwendeten Oracle-Treiber: ojdbc7.jar. Dieser Treiber ist für Oracle 12c und 11g gedacht, und es scheint, als ob er mit Oracle 10g verwendet wird, einige Probleme. Ich habe daher ein Downgrade auf ojdbc5.jar vorgenommen, und jetzt läuft alles einwandfrei.

0
gilbertoag

Ich hatte das gleiche Problem, weil ich db für mehr als 1000 Iterationen abgefragt habe. War aber immer noch fehlerhaft.

Um dieses Problem zu lösen, habe ich mich gerade bei Oracle db angemeldet und unter der folgenden Abfrage ausgeführt:

ALTER SYSTEM SET open_cursors = 8000 SCOPE = BEIDE;

Und damit wurde mein Problem sofort gelöst.

0
RArora

Dieses Problem tritt hauptsächlich dann auf, wenn Sie das Verbindungspooling verwenden, da beim Schließen der Verbindung diese Verbindung wieder zum Verbindungspool zurückkehrt und der mit dieser Verbindung verbundene Cursor nie geschlossen wird, da die Verbindung zur Datenbank noch geöffnet ist .. Eine Alternative ist Verringern Sie die Leerlaufverbindungszeit von Verbindungen im Pool. Wenn also die Verbindung 10 Sekunden lang inaktiv bleibt, wird die Verbindung zur Datenbank geschlossen und eine neue Verbindung zum Einrichten des Pools erstellt. 

0
Raveesh Badoni

Die Verwendung der Stapelverarbeitung führt zu weniger Aufwand. Beispiele finden Sie unter dem folgenden Link: http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm

0
Manjunath