java.sql.SQLException: - ORA-01000: перевищено максимально відкриті курсори


115

Я отримую виняток SQL ORA-01000. Тож у мене є запити, пов’язані з цим.

  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. Чи допоможе використання об'єкта слабкого / м'якого опорного висловлювання у запобіганні протікання?

Edit2: 1. Чи є якийсь спосіб, я можу знайти всі пропущені "statement.close ()" у своєму проекті? Я розумію, це не витік пам'яті. Але мені потрібно знайти посилання на заяву (де закриття () не виконується) придатне для вивезення сміття? Будь-який інструмент доступний? Або я маю це аналізувати вручну?

Будь ласка, допоможіть мені зрозуміти це.

Рішення

Щоб знайти відкритий курсор у БД Oracle для імені користувача -VELU

Перейдіть на машину 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) {
Єкоб

@ Kanagavelu Sugumar: чому б не задати 5 різних питань в ТА?
Jayan

1
Ось відповідь , який я знайшов дуже корисним: stackoverflow.com/a/4507507/501113
chaotic3quilibrium

Будь ласка, подивіться, чи корисна відповідь: stackoverflow.com/questions/34716456/…
Ману,

Для відстеження відкритих курсорів в Oracle ви також можете поглянути на SYS.V$OPEN_CURSORвигляд. Це дасть вам не тільки SID, але і текст SQL.
Бас

Відповіді:


290

ORA-01000, помилка максимально відкритих курсорів, є надзвичайно поширеною помилкою в розробці бази даних Oracle. У контексті Java це трапляється, коли програма намагається відкрити більше ResultSets, ніж налаштованих курсорів на екземплярі бази даних.

Поширені причини:

  1. Помилка конфігурації

    • У вашій програмі запит на базу даних більше, ніж курсори в БД. Один випадок, коли у вас є з'єднання та пул потоків, більший за кількість курсорів у базі даних.
    • У вас є багато розробників або додатків, підключених до одного екземпляра БД (який, ймовірно, включає багато схем), і разом ви використовуєте занадто багато з'єднань.
    • Рішення:

  2. Витік курсору

    • Програми не закривають ResultSets (в JDBC) або курсори (у збережених процедурах в базі даних)
    • Рішення : Протікання курсору - це помилки; збільшення кількості курсорів на БД просто затримує неминучий збій. Витоки можна знайти за допомогою статичного аналізу коду , JDBC або журналу на рівні додатків та моніторингу баз даних .

Фон

У цьому розділі описано деякі теорії, що стоять за курсорами, і як слід використовувати JDBC. Якщо вам не потрібно знати тло, ви можете пропустити це та перейти безпосередньо до "Усунення витоків".

Що таке курсор?

Курсор - це ресурс у базі даних, який містить стан запиту, зокрема позицію, де читач знаходиться в ResultSet. Кожен оператор SELECT має курсор, і збережені PL / SQL процедури можуть відкривати та використовувати стільки курсорів, скільки потрібно. Більше про курсори можна дізнатися на Orafaq .

Екземпляр бази даних, як правило, обслуговує декілька різних схем , безліч різних користувачів, які мають кілька сеансів . Для цього у нього є фіксована кількість курсорів, доступних для всіх схем, користувачів та сесій. Коли всі курсори відкриті (використовуються) і запит надходить, що вимагає нового курсору, запит не працює з помилкою ORA-010000.

Пошук та встановлення кількості курсорів

Номер зазвичай налаштовується DBA при встановленні. Кількість курсорів, які зараз використовуються, максимальна кількість та конфігурація можуть бути доступні в функціях адміністратора в Oracle SQL Developer . З SQL його можна встановити за допомогою:

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

Відношення JDBC в JVM до курсорів у БД

Нижче наведені об'єкти JDBC тісно пов'язані з такими концепціями бази даних:

  • JDBC Connection - це представлення клієнтом сеансу бази даних та забезпечує транзакції з базами даних . У з’єднанні може бути відкрита лише одна транзакція в будь-який час (але транзакції можуть бути вкладені)
  • JDBC ResultSet підтримується одним курсором бази даних. Коли виклик close () на ResultSet, курсор відпускається.
  • JDBC CallableStatement викликає збережену процедуру в базі даних, часто записану в PL / SQL. Збережена процедура може створити нульовий або більше курсорів і може повернути курсор як JDBC ResultSet.

JDBC є безпечним для потоків: цілком нормально передавати різні об'єкти JDBC між потоками.

Наприклад, ви можете створити з'єднання в одному потоці; інший потік може використовувати це з'єднання для створення PreparedStatement, а третій потік може обробити набір результатів. Єдине основне обмеження полягає в тому, що ви не можете будь-коли відкрити більше, ніж один ResultSet на одному Підготовленому стані. Побачити Чи підтримує Oracle DB декілька (паралельних) операцій на з'єднання?

Зауважте, що фіксація бази даних відбувається під час з'єднання, і тому всі DML (INSERT, UPDATE та DELETE) у цьому з'єднанні будуть здійснюватися разом. Тому, якщо ви хочете одночасно підтримувати декілька транзакцій, у вас має бути принаймні одне підключення для кожної супутньої транзакції.

Закриття об'єктів 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) { }
}

Зауважте, як остаточне зауваження ігнорує будь-який виняток, порушений функцією close ():

  • Якщо ви просто закриєте ResultSet без спроби {} catch {}, це може вийти з ладу і не допустити закриття заяви
  • Ми хочемо дозволити будь-яке виняток, що виникає в тілі спроби поширитись на абонента. Якщо у вас є цикл, наприклад, створення та виконання заяв, не забудьте закрити кожну заяву в циклі.

У Java 7 Oracle представив інтерфейс AutoCloseable, який замінює більшість котлів Java 6 на симпатичний синтаксичний цукор.

Зберігання об'єктів JDBC

Об'єкти JDBC можна безпечно утримувати в локальних змінних, екземплярах об'єктів та членах класу. Як правило, краща практика:

  • Використовуйте об'єкт об'єкта або учасників класу для утримання об'єктів JDBC, які повторно використовуються багато разів протягом більш тривалого періоду, таких як З'єднання та Підготовлені Стани
  • Використовуйте локальні змінні для ResultSets, оскільки вони отримані, перекинуті і закриті, як правило, в межах однієї функції.

Однак є один виняток: якщо ви використовуєте EJB або контейнер Servlet / JSP, вам слід дотримуватися суворої моделі нитки:

  • Тільки сервер додатків створює потоки (за допомогою яких він обробляє вхідні запити)
  • Тільки сервер додатків створює з'єднання (які ви отримуєте з пулу з'єднань)
  • Зберігаючи значення (стан) між дзвінками, ви повинні бути дуже обережними. Ніколи не зберігайте значення у власних кешах або статичних членах - це не безпечно для кластерів та інших дивних умов, і сервер додатків може робити страшні речі для ваших даних. Замість цього використовуйте видатні боби або базу даних.
  • Зокрема, ніколи не тримайте об’єкти JDBC (Connections, ResultSets, PreparedStatements тощо) над різними віддаленими викликами - нехай сервер програм керує цим. Сервер додатків не тільки забезпечує пул з'єднань, але також кешує ваші PreparedStatements.

Усунення витоків

Існує ряд процесів та інструментів, які допомагають виявити та усунути витоки JDBC:

  1. Під час розвитку - найчастіше підхоплення помилок - це найкращий підхід:

    1. Практики розробки: хороші практики розробки повинні зменшити кількість помилок у вашому програмному забезпеченні, перш ніж він залишає стіл розробника. Конкретні практики включають:

      1. Парне програмування , щоб навчати тих, хто не має достатнього досвіду
      2. Код оглядів оскільки багато очей краще, ніж одне
      3. Блок тестування що означає, що ви можете здійснювати будь-яку кодову базу коду за допомогою тестового інструменту, який робить відтворення витоків тривіальними
      4. Використовуйте наявні бібліотеки для об'єднання з'єднань, а не для створення власної
    2. Статичний аналіз коду: для аналізу статичного коду використовуйте такий інструмент, як відмінні Findbugs . Це підбирає багато місць, де закриття () не було належним чином оброблено. У Findbugs є плагін для Eclipse, але він також працює окремо для одноразових, має інтеграцію в CI Jenkins та інші інструменти побудови

  2. Під час виконання:

    1. Гідність та відданість

      1. Якщо вміст ResultSet є ResultSet.CLOSE_CURSORS_OVER_COMMIT, тоді ResultSet закривається, коли викликається метод Connection.commit (). Це можна встановити за допомогою Connection.setHoldability () або за допомогою методу перевантаженого Connection.createStatement ().
    2. Ведення журналу під час виконання.

      1. Введіть хороші виписки з журналу у свій код. Вони повинні бути чіткими і зрозумілими, щоб клієнт, обслуговуючий персонал та колеги могли зрозуміти без навчання. Вони повинні бути лаконічними і включати друк стану / внутрішніх значень ключових змінних та атрибутів, щоб можна було простежити логіку обробки. Хороший журнал є основним для налагодження програм, особливо тих, які були розгорнуті.
      2. Ви можете додати до свого проекту драйвер JDBC (для налагодження - фактично не розгортайте його). Один із прикладів (я цього не використовував) - log4jdbc . Потім потрібно зробити простий аналіз цього файлу, щоб побачити, які виконавці не мають відповідного закриття. Підрахунок відкритих та закритих має підкреслити, якщо є потенційна проблема

        1. Моніторинг бази даних. Контролюйте свою запущену програму за допомогою таких інструментів, як функція "Монітор SQL" розробника SQL або Quest's TOAD . Моніторинг описаний у цій статті . Під час моніторингу ви запитуєте відкриті курсори (наприклад, з таблиці v $ sesstat) та переглядаєте їх SQL. Якщо кількість курсорів збільшується і (головне) стає домінуючим одним ідентичним оператором SQL, ви знаєте, що у вас є витік із цим SQL. Шукайте свій код і перегляньте.

Інші думки

Чи можете ви використовувати WeakReferences для обробки з'єднань, що закриваються?

Слабкі та м'які посилання - це спосіб дозволити вам посилатись на об’єкт таким чином, що дозволяє JVM збирати сміття референта в будь-який час, який він вважає за потрібне (якщо припустити, що для цього об’єкта немає сильних ланцюгів відліку).

Якщо ви передаєте ReferenceQueue в конструкторі м'якому або слабкому посиланню, об'єкт розміщується в ReferenceQueue, коли об'єкт GC'ed, коли він виникає (якщо він взагалі виникає). При такому підході ви можете взаємодіяти з доопрацюванням об’єкта, і ви могли закрити або доопрацювати об’єкт у той момент.

Посилання на фантоми дещо дивніші; їх мета полягає лише в управлінні доопрацюванням, але ви ніколи не можете отримати посилання на оригінальний об'єкт, тому назвати на ньому метод close () буде важко.

Однак, дуже рідко є ідея спробувати контролювати, коли запускається GC (слабкі, м'які та PhantomReferences повідомляють вас після того , як об'єкт передається для GC). Насправді, якщо об'єм пам'яті в JVM великий (наприклад, -Xmx2000m), ви ніколи не зможете GC об'єктом, і ви все одно відчуєте ORA-01000. Якщо пам'ять JVM невелика щодо вимог вашої програми, ви можете виявити, що об'єкти ResultSet і PreparedStatement GCed одразу після створення (перш ніж ви зможете прочитати з них), що, ймовірно, не зможе програму.

TL; DR: Слабкий контрольний механізм не є хорошим способом керування та закриття об'єктів Statement та ResultSet.


3
Якщо ви створюєте заяви у циклі, переконайтеся, що він закритий у циклі, інакше ви закриєте лише останнє.
basiljames

Спасибі, базільяме. Щойно відредагувавши відповідь, яку потрібно додати в пункт, який ви зробили.
Ендрю Алькок

@ Ендрю Алькок Дякую! Андрій. Чи можете ви, будь ласка, відповісти і на 6-му.
Канагавелу Сугумар

@AndrewAlcock Будь ласка .. будь ласка .. будь ласка .. відповідь також на моє сьоме запитання. З моменту нашого проекту ми дуже часто стикаємось з ORA-01000 під час тестування навантаження. Ваші вклади для мене цінніші. Заздалегідь дякую тоні !!
Канагавелу Сугумар

RE: 7 - ви можете спробувати пошук близькості за допомогою такого інструменту, як grep. Коли ви розпізнаєте SQL (виберіть, вставіть, оновіть, видаліть), перегляньте близькість слова close () поруч із твердженням. Якщо близькість знаходиться далі, ніж очікувалося, це може бути способом розслідувати, де вона відсутня. lightboxtechnologies.com/2012/07/27 / ...
Нд

28

Я додаю ще трохи розуміння.

  1. Курсор стосується лише об'єкта заяви; Він не є ні результатом набору, ні об'єктом з'єднання.
  2. Але все ж нам потрібно закрити набір результатів, щоб звільнити деяку пам’ять oracle. Але якщо ви не закриєте набір результатів, це не зараховуватиметься до CURSORS.
  3. Об'єкт заяви про закриття також автоматично закриє об'єкт набору результатів.
  4. Курсор буде створений для всіх операторів SELECT / INSERT / UPDATE / DELETE.
  5. Кожен екземпляр бази даних ORACLE можна ідентифікувати за допомогою Oracle SID; аналогічно ORACLE DB може ідентифікувати кожне з'єднання за допомогою SID з'єднання. Обидва SID різні.
  6. Отже, сеанс ORACLE - це не що інше, як з'єднання jdbc (tcp); що не що інше, як один SID.
  7. Якщо ми встановимо максимальні курсори як 500, то це лише для одного JDBC-сеансу / з'єднання / SID.
  8. Таким чином, ми можемо мати багато з'єднань JDBC з відповідним числом курсорів (операторів).
  9. Щойно JVM припиняється, всі з'єднання / курсори будуть закриті, АБО JDBCCз'єднання закрите, КУРСИ щодо цього з'єднання будуть закриті.

Увійти як 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'

Виберіть існуючий набір оцінок 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

Якщо ваша програма являє собою додаток Java EE, що працює на Oracle WebLogic як сервер додатків, можливою причиною цієї проблеми є налаштування розміру кешу оператора в WebLogic.

Якщо налаштування розміру кешу оператора для конкретного джерела даних приблизно дорівнює або більше, ніж параметр максимальної кількості відкритих курсорів бази даних Oracle, то всі відкриті курсори можуть бути використані кешованими операторами SQL, які є відкритими WebLogic, в результаті чого в помилці ORA-01000

Для вирішення цього питання зменшіть налаштування розміру кешу оператора для кожного джерела даних WebLogic, який вказує на базу даних Oracle, щоб бути значно меншим, ніж максимальний параметр кількості курсорів у базі даних.

На консолі адміністратора WebLogic 10 налаштування розміру кешу оператора для кожного джерела даних можна знайти у розділі Служби (зліва)> Джерела даних> (окреме джерело даних)> Вкладка Пул підключення.


1
Hibernate також має кеш оператора. Дивіться також developer.jboss.org/wiki/…
Піно

3

Я теж стикався з цим питанням. Нижче був виняток

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

Я використовував Spring Framework з Spring JDBC для шару дао.

Моя програма використовувалась для витоку курсорів якось і через декілька хвилин, і раніше мені це було винятком.

Після багато ретельного налагодження та аналізу я виявив, що в одній із таблиць, що використовуються у запиті, який я виконував, в одній із таблиць, що використовувалась , я виявила проблему з індексуванням, первинним ключем та унікальними обмеженнями .

Моя програма намагалася оновити стовпці, які були помилково індексовані . Отже, щоразу, коли моя програма потрапляла на запит оновлення в індексованих стовпцях, База даних намагалася зробити реіндексінг на основі оновлених значень. Це просочилося курсорами .

Мені вдалося вирішити проблему, виконавши належну індексацію на стовпцях, які використовувались для пошуку в запиті, та застосувавши відповідні обмеження, де це було потрібно.


2

Я зіткнувся з тією ж проблемою (ORA-01000) сьогодні. У спробу {} я багато разів виконував операцію SELECT у БД Oracle (щоразу змінюючи параметр), і, нарешті, {} у мене був код закрити Resultset, PreparedStatement та Connection як завжди . Але як тільки я досяг певної кількості циклів (1000), у мене з’явилася помилка Oracle щодо занадто багато відкритих курсорів.

Виходячи з публікації Ендрю Алькока вище, я вніс зміни, щоб всередині циклу я закрив кожен набір результатів і кожне твердження після отримання даних і перед повторним циклом, і це вирішило проблему.

Крім того, саме таку ж проблему виникло в іншому циклі Insert Statements, в іншій БД Oracle (ORA-01000), цього разу після 300 заяв. Знову це було вирішено таким же чином, тому або Підготовлені Станції, або ResultSet, або обидва, вважайте відкритими курсорами, поки вони не будуть закриті.


Це не здається правильним. Весняні документи, що відповідає за закриття ResultSets ( 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 

Чи можете ви відповісти на інші запитання?
Канагавелу Сугумар

2
Автокомісія не закриває з'єднання - вона автоматично автоматично виконує кожну операцію відразу після її виконання. Якщо ви користуєтесь автокомісією, ви не отримуєте значення від одного з найважливіших властивостей бази даних - транзакцій. Ви можете замість цього використати БД NoSQL.
Ендрю Алькок

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

Ця проблема в основному виникає, коли ви використовуєте пул з'єднань, тому що коли ви закриваєте з'єднання, повертайтеся до пулу з'єднань, і весь курсор, пов'язаний із цим з'єднанням, ніколи не закривається, оскільки з'єднання з базою даних все ще відкрите. Таким чином, однією з альтернатив є скорочення простою часу з'єднання з'єднань у пулі, тому, коли з'єднання буде простоювати у зв'язку, наприклад, 10 сек, підключення до бази даних закриється, а нове з'єднання буде створене для розміщення в пулі.



0

У нашому випадку ми використовували Hibernate, і у нас було багато змінних, що посилаються на одне ціле сплячене зі сплячим режимом. Ми створювали та зберігали ці посилання в циклі. Кожна посилання відкривала курсор і тримала його відкритим.

Ми виявили це за допомогою запиту, щоб перевірити кількість відкритих курсорів під час запуску нашого коду, перейшовши через налагоджувач і вибірково коментуючи речі.

Щодо того, чому кожна нова посилання відкриває інший курсор - відповідна сутність має колекції інших сутностей, відображені на ній, і я думаю, що це мало щось із цим (можливо, не тільки це одне, але в поєднанні з тим, як ми налаштували режим отримання та налаштування кеша). У самому сплячому стані помилки не вдалося закрити відкриті курсори, хоча, схоже, вони були виправлені в пізніших версіях.

Оскільки нам не потрібно було мати стільки повторюваних посилань на одну і ту ж сутність, рішенням було зупинити створення та затримати всі ці зайві посилання. Одного разу ми зробили цю проблему, коли віддалилися.


0

У мене виникли проблеми з моїм джерелом даних у WildFly та Tomcat, підключення до Oracle 10g.

Я виявив, що за певних умов виписка не закрита, навіть коли було викликано заяву.close (). Проблема була з драйвером Oracle, який ми використовували: ojdbc7.jar. Цей драйвер призначений для Oracle 12c та 11g, і, здається, є деякі проблеми, коли він використовується з Oracle 10g, тому я переходжу на ojdbc5.jar і тепер все працює нормально.


0

Я зіткнувся з тією ж проблемою, тому що я запитував db для більш ніж 1000 ітерацій. Я використав спробу і, нарешті, у своєму коді. Але все-таки отримувала помилку.

Щоб вирішити це, я просто увійшов до Oracle db і побіг нижче запиту:

ALTER SYSTEM SET open_cursors = 8000 ОБЛАСТЬ = ВІД;

І це негайно вирішило мою проблему.


Це врятувало деякі симптоми, але насправді не вирішило проблему. Вам потрібно виправити свій код, щоб він закривав курсори, коли він закінчився з ними.
APC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.