java.sql.SQLException:-ORA-01000:オープンカーソルの最大数を超えました


115

ORA-01000 SQL例外が発生します。それに関連するクエリがあります。

  1. 最大オープンカーソルはJDBC接続の数に正確に関連していますか、それとも、単一の接続用に作成したステートメントと結果セットオブジェクトにも関連していますか?(接続プールを使用しています)
  2. データベース内のステートメント/結果セットオブジェクトの数(接続など)を構成する方法はありますか?
  3. シングルスレッド環境では、メソッドローカルステートメント/結果セットオブジェクトの代わりにインスタンス変数ステートメント/結果セットオブジェクトを使用することをお勧めしますか?
  4. 準備されたステートメントをループで実行すると、この問題が発生しますか?(もちろん、sqlBatchを使用することもできます)注:ループが終了するとpStmtが閉じます。

    { //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. 単一の接続オブジェクトでconn.createStatement()およびconn.prepareStatement(sql)が複数回呼び出されるとどうなりますか?

Edit1: 6. Weak / Soft参照ステートメントオブジェクトの使用は、リークの防止に役立ちますか?

Edit2: 1.プロジェクトに欠落している「statement.close()」をすべて見つける方法はありますか?メモリリークではないことを理解しています。しかし、ガベージコレクションに適したステートメント参照(close()が実行されない場所)を見つける必要がありますか?利用可能なツールはありますか?それとも手動で分析する必要がありますか?

理解してください。

解決

ユーザー名-VELUのOracle DBで開かれたカーソルを見つけるには

ORACLEマシンに移動し、sqlplusをsysdbaとして起動します。

[oracle@db01 ~]$ sqlplus / as sysdba 

次に実行します

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

可能であれば、私の答えを読んで私の解決策をもっと理解してください


完全なコードを投稿できますか?あなたのために開かれたオープニングかっこ閉じているところを見るのは興味深いだろうfor (String language : additionalLangs) {
ヤコブ

@カナガベルスグマール:SOで5つの異なる質問をしてみませんか?
Jayan

1
これが私がとても役に立ったと思った応答です:stackoverflow.com/a/4507507/501113
chaotic3quilibrium

:答えは便利ですかどうかを確認してくださいstackoverflow.com/questions/34716456/...
マヌ

Oracleで開いているカーソルを追跡するには、SYS.V$OPEN_CURSORビューを確認することもできます。これにより、SIDだけでなくSQLテキストも得られます。
Bass

回答:


290

最大オープンカーソルエラーであるORA-01000は、Oracleデータベース開発で非常に一般的なエラーです。Javaのコンテキストでは、データベースインスタンスに設定されたカーソルよりも多くのResultSetをアプ​​リケーションが開こうとしたときに発生します。

一般的な原因は次のとおりです。

  1. 設定ミス

    • DB上のカーソルよりも、データベースをクエリするアプリケーション内のスレッドが多くなっています。1つのケースは、データベース上のカーソルの数よりも大きい接続とスレッドプールがある場合です。
    • 多くの開発者またはアプリケーションが同じDBインスタンス(おそらく多くのスキーマを含む)に接続されており、一緒に使用している接続が多すぎます。
    • 解決:

      • データベースのカーソル数を増やす(リソースで可能な場合)または
      • アプリケーションのスレッド数を減らします。
  2. カーソルリーク

    • アプリケーションがResultSets(JDBC)またはカーソル(データベースのストアドプロシージャ)を閉じていない
    • 解決策:カーソルリークはバグです。DB上のカーソルの数を増やすと、避けられない障害が遅延するだけです。リークは、静的コード分析JDBCまたはアプリケーションレベルのロギング、データベースモニタリングを使用して検出できます。

バックグラウンド

このセクションでは、カーソルの背後にある理論と、JDBCの使用方法について説明します。背景を知る必要がない場合は、これをスキップして「リークの除去」に進んでください。

カーソルとは何ですか?

カーソルとは、クエリの状態、特にResultSet内のリーダーの位置を保持するデータベース上のリソースです。各SELECT文にはカーソルがあり、PL / SQLストアドプロシージャは、必要な数のカーソルを開いて使用できます。Orafaqのカーソルについて詳しく知ることができます。

データベースインスタンスは通常、いくつかの異なるスキーマ、それぞれに複数のセッションを持つ多くの異なるユーザーにサービスを提供します。これを行うために、すべてのスキーマ、ユーザー、およびセッションで使用可能なカーソルの数が固定されています。すべてのカーソルが開いていて(使用中)、新しいカーソルを必要とする要求が入ってくると、要求はORA-010000エラーで失敗します。

カーソルの数を見つけて設定する

この数は通常、インストール時にDBAによって構成されます。現在使用中のカーソルの数、最大数、および構成には、Oracle SQL Developerの管理者機能でアクセスできます。SQLからは、次のように設定できます。

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

JVM内のJDBCをDB上のカーソルに関連付ける

以下のJDBCオブジェクトは、次のデータベースの概念と密接に関連しています。

  • JDBC 接続は、データベースセッションのクライアント表現であり、データベーストランザクションを提供します。接続は一度に1つのトランザクションのみを開くことができます(ただし、トランザクションはネストできます)
  • JDBC ResultSetは、データベース上の単一のカーソルでサポートされています。ResultSetでclose()が呼び出されると、カーソルが解放されます。
  • JDBC CallableStatementは、多くの場合PL / SQLで記述されたデータベースのストアドプロシージャを呼び出します。ストアドプロシージャは0個以上のカーソルを作成でき、JDBC ResultSetとしてカーソルを返すことができます。

JDBCはスレッドセーフです。スレッド間でさまざまなJDBCオブジェクトを渡しても問題ありません。

たとえば、1つのスレッドで接続を作成できます。別のスレッドがこの接続を使用してPreparedStatementを作成でき、3番目のスレッドが結果セットを処理できます。単一の主な制限は、単一のPreparedStatementで同時に複数のResultSetを開くことはできないということです。Oracle DBは接続ごとに複数の(並列)操作をサポートしていますか?を参照してください

データベースのコミットは接続で発生するため、その接続のすべてのDML(INSERT、UPDATE、DELETE)が一緒にコミットすることに注意してください。したがって、同時に複数のトランザクションをサポートする場合は、同時トランザクションごとに少なくとも1つの接続が必要です。

JDBCオブジェクトを閉じる

ResultSetを実行する一般的な例は次のとおりです。

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) { }
}

finally節がclose()で発生した例外を無視する方法に注意してください:

  • try {} catch {}を使用せずに単にResultSetを閉じると、失敗し、ステートメントが閉じられなくなる可能性があります
  • tryの本文で発生した例外を呼び出し元に伝播できるようにしたいと考えています。ステートメントを作成して実行するなど、ループオーバーがある場合は、ループ内の各ステートメントを閉じることを忘れないでください。

Java 7では、OracleはAutoCloseableインターフェースを導入しました。これは、Java 6ボイラープレートのほとんどをいくつかの素晴らしい構文上の砂糖に置き換えます

JDBCオブジェクトの保持

JDBCオブジェクトは、ローカル変数、オブジェクトインスタンス、およびクラスメンバーに安全に保持できます。一般に、次のことをお勧めします。

  • オブジェクトインスタンスまたはクラスメンバーを使用して、ConnectionsやPreparedStatementsなど、長期間にわたって複数回再利用されるJDBCオブジェクトを保持します。
  • ResultSetにはローカル変数を使用します。これらは取得され、ループされ、通常は単一の関数のスコープ内で閉じられるためです。

ただし、1つの例外があります。EJB、またはサーブレット/ JSPコンテナを使用している場合は、厳密なスレッドモデルに従う必要があります。

  • アプリケーションサーバーのみがスレッドを作成します(スレッドを使用して着信要求を処理します)。
  • アプリケーションサーバーのみが接続を作成します(接続プールから取得)
  • 呼び出し間で値(状態)を保存するときは、非常に注意する必要があります。独自のキャッシュまたは静的メンバーに値を格納しないでください。これは、クラスター全体および他の奇妙な条件全体で安全ではなく、アプリケーションサーバーはデータに対してひどいことを行う可能性があります。代わりに、ステートフルBeanまたはデータベースを使用してください。
  • 特に、さまざまなリモート呼び出しでJDBCオブジェクト(接続、ResultSet、PreparedStatementsなど)を保持しないでください。アプリケーションサーバーでこれを管理してください。Application Serverは接続プールを提供するだけでなく、PreparedStatementsもキャッシュします。

漏れをなくす

JDBCリークの検出と排除に役立つプロセスとツールがいくつかあります。

  1. 開発中-バグを早期にキャッチするのが最善の方法です。

    1. 開発プラクティス:優れた開発プラクティスは、ソフトウェアが開発者のデスクを離れる前に、ソフトウェアのバグの数を減らす必要があります。具体的な方法は次のとおりです。

      1. ペアプログラミング、十分な経験がない人を教育する
      2. 多くの目は1つよりも優れているため、コードレビュー
      3. 単体テスト。これは、リークの再現を簡単にするテストツールからコードベースの一部またはすべてを実行できることを意味します。
      4. 独自のライブラリを構築するのではなく、既存のライブラリを接続プーリングに使用します
    2. 静的コード分析:優れたFindbugsなどのツールを使用して、静的コード分析を実行します。これにより、close()が正しく処理されなかった多くの場所が選択されます。FindbugsにはEclipse用のプラグインがありますが、1回限りのスタンドアロンで実行され、Jenkins CIおよび他のビルドツールに統合されています

  2. 実行時:

    1. 保持可能性とコミット

      1. ResultSetの保持機能がResultSet.CLOSE_CURSORS_OVER_COMMITの場合、Connection.commit()メソッドが呼び出されると、ResultSetは閉じられます。これは、Connection.setHoldability()を使用するか、オーバーロードされたConnection.createStatement()メソッドを使用して設定できます。
    2. 実行時のロギング。

      1. コードに適切なログステートメントを挿入します。顧客、サポートスタッフ、チームメートがトレーニングなしで理解できるように、これらは明確で理解できるものでなければなりません。それらは簡潔で、処理ロジックをトレースできるように、主要な変数と属性の状態/内部値の出力を含む必要があります。優れたロギングは、特にデプロイされているアプリケーションをデバッグするための基本です。
      2. デバッグ用のJDBCドライバーをプロジェクトに追加できます(デバッグ用-実際にはデプロイしないでください)。1つの例(私はそれを使用していません)はlog4jdbcです。次に、このファイルで簡単な分析を行い、どの実行に対応する終了がないかを確認する必要があります。オープンとクローズを数えることは、潜在的な問題があるかどうかを強調する必要があります

        1. データベースの監視。SQL開発者の「SQLの監視」機能やQuestのTOADなどのツールを使用して、実行中のアプリケーションを監視します。監視については、この記事で説明します。監視中に、開いているカーソル(テーブルv $ sesstatなど)に対してクエリを実行し、それらのSQLを確認します。カーソルの数が増加し、そして(最も重要なことに)1つの同一のSQLステートメントによって支配されるようになった場合、そのSQLにリークがあることがわかります。コードを検索して確認します。

他の考え

WeakReferencesを使用して接続のクローズを処理できますか?

弱参照とソフト参照は、JVMが適合と見なすときにいつでも参照をガベージコレクションできるようにオブジェクトを参照できるようにする方法です(そのオブジェクトへの強い参照チェーンがない場合)。

コンストラクター内のReferenceQueueをソフトまたはウィークリファレンスに渡す場合、オブジェクトが発生したときにオブジェクトがGCされたとき(発生した場合)、オブジェクトはReferenceQueueに配置されます。このアプローチを使用すると、オブジェクトのファイナライズを操作でき、その時点でオブジェクトをクローズまたはファイナライズできます。

ファントム参照は少し奇妙です。それらの目的はファイナライズを制御することだけですが、元のオブジェクトへの参照を取得することはできないため、そのオブジェクトでclose()メソッドを呼び出すのは困難です。

ただし、GCの実行を制御しようとすることはめったにありません(オブジェクトがGCのキューに入れられた後で、 Weak、Soft、およびPhantomReferencesから通知されます)。実際、JVMのメモリ容量が大きい場合(例:-Xmx2000m)、オブジェクトをGCしない可能性があり、ORA-01000が引き続き発生します。JVMメモリがプログラムの要件に比べて小さい場合、ResultSetオブジェクトとPreparedStatementオブジェクトが作成直後に(それらから読み取ることができる前に)GCされ、プログラムが失敗する可能性があります。

TL; DR:弱い参照メカニズムは、StatementオブジェクトとResultSetオブジェクトを管理して閉じるための良い方法ではありません。


3
ループ内でステートメントを作成する場合は、ループ内でステートメントが閉じていることを確認してください。閉じていない場合、最後のステートメントのみが閉じてしまいます。
basiljames 2012

ありがとう、バジルジャム。回答を編集して、作成したポイントを追加します。
アンドリューアルコック

@ Andrew Alcockありがとうございます!アンドリュー。6日もお答えください。
Kanagavelu Sugumar 2012

@AndrewAlcockプリーズ..プリーズ..プリーズ..私の7番目の質問にも答えてください。私たちのプロジェクト以来、負荷テストの間、ORA-01000に非常に頻繁に直面しています。あなたのインプットは私にとってより価値があります。よろしくお願いします!!
Kanagavelu Sugumar 2012

RE:7-grepなどのツールを使用して近接検索を試すことができます。SQL(選択、挿入、更新、削除)を認識したら、ステートメントの横にある単語close()の近接性を確認してください。近接度が予想よりも離れている場合、それが欠落している場所を調査する方法となる場合があります。lightboxtechnologies.com/2012/07/27/...

28

私はもう少し理解を加えています。

  1. カーソルはステートメントオブジェクトのみに関するものです。これは、resultSetでも接続オブジェクトでもありません。
  2. しかし、まだOracleのメモリを解放するために、結果セットを閉じる必要があります。それでも、CURSORSとしてカウントされない結果セットを閉じない場合。
  3. Statementオブジェクトを閉じると、結果セットオブジェクトも自動的に閉じます。
  4. すべてのSELECT / INSERT / UPDATE / DELETEステートメントに対してカーソルが作成されます。
  5. 各ORACLE DBインスタンスは、Oracle SIDを使用して識別できます。同様に、ORACLE DBは接続SIDを使用して各接続を識別できます。両方のSIDが異なります。
  6. したがって、ORACLEセッションはjdbc(tcp)接続にすぎません。これは1つのSIDにすぎません。
  7. 最大カーソル数を500に設定すると、1つのJDBCセッション/接続/ SIDのみが対象になります。
  8. したがって、それぞれのカーソル(ステートメント)がない状態で多くのJDBC接続を確立できます。
  9. JVMが終了すると、すべての接続/カーソルが閉じます。または、JDBCConnectionが閉じます。その接続に関してCURSORSが閉じます。

sysdbaとしてログインします。

Putty(Oracleログイン):

  [oracle@db01 ~]$ sqlplus / as sysdba

SqlPlusの場合:

ユーザー名: sys as sysdba

カーソルを閉じないように、session_cached_cursorsの値を0に設定します。

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

DBの接続ごとに既存のOPEN_CURSORS値セットを選択します

 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;

以下は、オープンカーソル値を含むSID /接続リストを検索するクエリです。

 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'

以下のクエリを使用して、開いているカーソル内のSQLを特定します

 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'

コードをデバッグしてお楽しみください!!! :)


1
ここではうまく動作しているようです別のクエリは次のとおりです。stackoverflow.com/a/2560415/32453
rogerdpack

4

次のようにコードを修正します。

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()
} 

本当に、pStatements、接続、および結果を閉じていることを確信していますか?

オープンオブジェクトを分析するには、デリゲートパターンを実装できます。デリゲートパターンは、ステートマント、接続、および結果オブジェクトの周りにコードをラップします。したがって、オブジェクトが正常に閉じられるかどうかがわかります。

例: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");
        }
    }
}

3

アプリケーションがOracle WebLogicでアプリケーションサーバーとして実行されているJava EEアプリケーションの場合、この問題の原因として考えられるのはステートメントキャッシュサイズです。 WebLogicの設定です。

特定のデータソースのステートメントキャッシュサイズの設定がOracleデータベースの最大オープンカーソル数の設定とほぼ同じかそれより大きい場合、オープンカーソルはすべて、WebLogicによってオープンに保持されているキャッシュされたSQLステートメントによって消費され、結果としてORA-01000エラー。

これに対処するには、Oracleデータベースを指す各WebLogicデータソースのステートメントキャッシュサイズ設定を、データベースの最大カーソル数設定よりも大幅に小さくします。

WebLogic 10管理コンソールでは、各データソースのステートメントキャッシュサイズ設定は、サービス(左ナビゲーション)>データソース>(個別のデータソース)>接続プールタブにあります。


1
Hibernateにもステートメントキャッシュがあります。developer.jboss.org/wiki/…
Pino

3

私もこの問題に直面していました。

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

私は、DAOレイヤーのSpring JDBCSpring Frameworkを使用していました。

私のアプリケーションは、どういうわけかカーソルをリークしていました。数分後、この例外が発生していました。

多くの徹底的なデバッグと分析の結果、実行中のクエリで使用されているテーブルの 1つにあるインデックス、主キー、一意の制約に問題があることがわかりました。

私のアプリケーションは、誤ってインデックス化されたを更新しようとしました。そのため、アプリケーションがインデックス付きの列で更新​​クエリを実行するたびに、データベースは更新された値に基づいて再インデックスを実行しようとしました。カーソルがリークしていました。

クエリの検索に使用される列に対して適切なインデックス付けを行い、必要に応じて適切な制約を適用することで、問題を解決することができました。


2

今日、同じ問題(ORA-01000)に直面しました。try {}にforループがあり、Oracle DBでSELECTステートメントを何度も(パラメータを変更するたびに)実行し、finally {}で、通常どおり、Resultset、PreparedStatement、およびConnectionを閉じるコードを作成しました。しかし、特定のループ数(1000)に達するとすぐに、開いているカーソルが多すぎるというOracleエラーが表示されました。

上記のAndrew Alcockの投稿に基づいて、ループ内でデータを取得した後、再びループする前に、各結果セットと各ステートメントを閉じるように変更を加え、問題を解決しました。

さらに、今度は300ステートメントの後、別のOracle DB(ORA-01000)のInsertステートメントの別のループでもまったく同じ問題が発生しました。再び同じ方法で解決されたため、PreparedStatementまたはResultSet、あるいはその両方が、閉じられるまで開いたカーソルとしてカウントされます。


これは正しくないようです。Springは、ResultSetを閉じる責任があることをドキュメント化します(docs.spring.io/spring/docs/current/spring-framework-reference/…)。
ライアン

わかりやすくするために、これらの例ではSpringを使用していませんでした。
Kinnison84

1

autocommit = trueを設定しましたか?これを試していない場合:

{ //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 

他の質問にもお答えください。
Kanagavelu Sugumar 2012

2
自動コミットは接続を閉じません-各ステートメントを実行直後に自動的にコミットするだけです。自動コミットを使用している場合、データベースの最も重要なプロパティの1つであるトランザクションから値を取得していません。代わりにNoSQL DBの使用を検討してください。
アンドリューアルコック

1

開いたSQLを検索するクエリ。

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

この問題は主に接続プーリングを使用しているときに発生します。接続を閉じると、その接続は接続プールに戻り、データベースへの接続がまだ開いているため、その接続に関連付けられているすべてのカーソルは決して閉じられないためです。したがって、1つの代替策は、プール内の接続のアイドル接続時間を減らすことです。そのため、接続が接続中にアイドル状態で約10秒間待機すると、データベースへの接続が閉じられ、新しい接続が作成されてプールに入れられます。



0

私たちのケースでは、Hibernateを使用しており、同じHibernateマッピングエンティティを参照する多くの変数がありました。これらの参照をループで作成して保存していました。各参照はカーソルを開き、開いたままにしました。

コードを実行中にクエリを使用して開いているカーソルの数を確認し、デバッガーを使用してステップスルーし、選択的にコメント化することで、これを発見しました。

新しい参照がそれぞれ別のカーソルを開いた理由について-問題のエンティティはそれにマップされた他のエンティティのコレクションを持っていて、これはそれと何か関係があると思います(おそらくこれだけではなく、フェッチモードの構成方法と組み合わせて、キャッシュ設定)。Hibernate自体には、開いているカーソルを閉じるのに失敗するというバグがありましたが、それ以降のバージョンでは修正されているようです。

とにかく、同じエンティティへの重複した参照をそれほど多く持つ必要はなかったので、解決策は、これらのすべての冗長な参照の作成と保持を停止することでした。一度私たちが離れたときにその問題をしました。


0

WildFlyとTomcatのデータソースでOracle 10gに接続すると、この問題が発生しました。

特定の条件下では、statement.close()が呼び出されてもステートメントが閉じられないことがわかりました。問題は、使用していたOracleドライバー(ojdbc7.jar)にありました。このドライバーはOracle 12cおよび11gを対象としており、Oracle 10gで使用すると問題が発生する可能性があるため、ojdbc5.jarにダウングレードするとすべて正常に動作します。


0

1000回を超える反復でdbをクエリしていたため、同じ問題に直面しました。私はtryを使用し、最後にコードで使用しました。しかし、まだエラーが発生していました。

これを解決するために、私はoracle dbにログインし、以下のクエリを実行しました。

ALTER SYSTEM SET open_cursors = 8000 SCOPE = BOTH;

そして、これはすぐに私の問題を解決しました。


これはいくつかの症状を救いましたが、実際には問題を解決しませんでした。カーソルが終了したらカーソルを閉じるようにコードを修正する必要があります。
APC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.