Я получаю исключение SQL ORA-01000. Так что у меня есть несколько вопросов, связанных с этим.
- Связано ли максимальное количество открытых курсоров с количеством подключений JDBC, или они также связаны с объектами операторов и наборов результатов, которые мы создали для одного подключения? (Мы используем пул подключений)
- Есть ли способ настроить количество объектов инструкции / набора результатов в базе данных (например, соединений)?
- Целесообразно ли использовать оператор переменной экземпляра / объект набора результатов вместо объекта локального оператора / набора результатов метода в однопоточной среде?
Вызывает ли эту проблему выполнение подготовленного оператора в цикле? (Конечно, я мог бы использовать 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
Что произойдет, если conn.createStatement () и conn.prepareStatement (sql) будут вызваны несколько раз для одного объекта подключения?
Edit1: 6. Поможет ли использование объекта Weak / Soft reference statement в предотвращении утечки?
Edit2: 1. Есть ли способ найти все отсутствующие "statement.close ()" в моем проекте? Я так понимаю, это не утечка памяти. Но мне нужно найти ссылку на инструкцию (где close () не выполняется), подходящую для сборки мусора? Любой доступный инструмент? Или надо вручную анализировать?
Пожалуйста, помогите мне понять это.
Решение
Найти открытый курсор в Oracle DB для имени пользователя -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) {
SYS.V$OPEN_CURSOR
представление. Это даст вам не только SID, но и текст SQL.Ответы:
ORA-01000, ошибка максимального количества открытых курсоров, является чрезвычайно распространенной ошибкой при разработке баз данных Oracle. В контексте Java это происходит, когда приложение пытается открыть больше ResultSets, чем настроено курсоров в экземпляре базы данных.
Общие причины:
Ошибка конфигурации
Решение:
Утечка курсора
Задний план
В этом разделе описываются некоторые теории курсоров и способы использования JDBC. Если вам не нужно знать предысторию, вы можете пропустить это и сразу перейти к «Устранению утечек».
Что такое курсор?
Курсор - это ресурс в базе данных, который хранит состояние запроса, в частности позицию, в которой читатель находится в ResultSet. У каждого оператора SELECT есть курсор, а хранимые процедуры PL / SQL могут открывать и использовать столько курсоров, сколько им требуется. Вы можете узнать больше о курсорах на Orafaq .
Экземпляр базы данных обычно обслуживает несколько разных схем , много разных пользователей, каждая с несколькими сеансами . Для этого у него есть фиксированное количество курсоров, доступных для всех схем, пользователей и сеансов. Когда все курсоры открыты (используются) и поступает запрос, требующий нового курсора, запрос завершается ошибкой ORA-010000.
Поиск и установка количества курсоров
Номер обычно настраивается администратором баз данных при установке. Количество используемых курсоров, максимальное количество и конфигурация доступны в функциях администратора в Oracle SQL Developer . Из SQL это можно установить с помощью:
Связь JDBC в JVM с курсорами в БД
Приведенные ниже объекты JDBC тесно связаны со следующими концепциями базы данных:
JDBC является потокобезопасным: вполне нормально передавать различные объекты JDBC между потоками.
Например, вы можете создать соединение в одном потоке; другой поток может использовать это соединение для создания PreparedStatement, а третий поток может обработать набор результатов. Единственное серьезное ограничение заключается в том, что вы не можете одновременно открывать более одного ResultSet на одном PreparedStatement. См. Поддерживает ли база данных Oracle несколько (параллельных) операций на одно соединение?
Обратите внимание, что фиксация базы данных происходит в соединении, и поэтому все DML (INSERT, UPDATE и DELETE) в этом соединении будут фиксироваться вместе. Следовательно, если вы хотите поддерживать несколько транзакций одновременно, у вас должно быть хотя бы одно соединение для каждой параллельной транзакции.
Закрытие объектов JDBC
Типичный пример выполнения ResultSet:
Обратите внимание, как предложение finally игнорирует любое исключение, вызванное close ():
В Java 7 Oracle представила интерфейс AutoCloseable, который заменяет большую часть шаблонного кода Java 6 некоторым приятным синтаксическим сахаром.
Хранение объектов JDBC
Объекты JDBC можно безопасно хранить в локальных переменных, экземплярах объекта и членах класса. Как правило, лучше:
Однако есть одно исключение: если вы используете EJB или контейнер сервлетов / JSP, вы должны следовать строгой модели потоковой передачи:
Устранение утечек
Существует ряд процессов и инструментов, помогающих обнаруживать и устранять утечки JDBC:
Во время разработки - безусловно, лучший подход - выявление ошибок на раннем этапе:
Практика разработки: передовая практика разработки должна уменьшить количество ошибок в вашем программном обеспечении, прежде чем оно покинет рабочий стол разработчика. Конкретные практики включают:
Статический анализ кода: используйте такой инструмент, как отличный Findbugs, для выполнения статического анализа кода. Это обнаруживает многие места, где close () не обрабатывалась правильно. У Findbugs есть плагин для Eclipse, но он также работает автономно для разовых работ, имеет интеграцию с Jenkins CI и другими инструментами сборки.
Во время выполнения:
Удерживаемость и фиксация
Ведение журнала во время выполнения.
Вы можете добавить отладочный драйвер JDBC в свой проект (для отладки - фактически не развертывайте его). Один из примеров (я его не использовал) - log4jdbc . Затем вам нужно провести простой анализ этого файла, чтобы увидеть, какие из выполнений не имеют соответствующего закрытия. Подсчет числа открытых и закрытых должен выявить потенциальную проблему.
Другие мысли
Можете ли вы использовать WeakReferences для обработки закрывающихся соединений?
Слабые и мягкие ссылки - это способы, позволяющие вам ссылаться на объект таким образом, который позволяет JVM собирать мусор для референта в любое время, которое она сочтет нужным (при условии, что на этот объект нет сильных цепочек ссылок).
Если вы передаете ReferenceQueue в конструкторе мягкой или слабой ссылке, объект помещается в ReferenceQueue, когда объект GC'ed, когда он возникает (если это происходит вообще). При таком подходе вы можете взаимодействовать с финализацией объекта, и вы можете закрыть или финализировать объект в этот момент.
Фантомные ссылки немного страннее; их цель - только контролировать финализацию, но вы никогда не сможете получить ссылку на исходный объект, поэтому будет сложно вызвать для него метод close ().
Однако попытка управления запуском GC редко бывает хорошей идеей (Weak, Soft и PhantomReferences сообщают вам после того , как объект поставлен в очередь для GC). Фактически, если объем памяти в JVM велик (например, -Xmx2000m), вы можете никогда не выполнить сборку мусора для объекта, но все равно столкнетесь с ORA-01000. Если память JVM мала по сравнению с требованиями вашей программы, вы можете обнаружить, что объекты ResultSet и PreparedStatement собираются сразу после создания (до того, как вы сможете их читать), что, скорее всего, приведет к сбою вашей программы.
TL; DR: слабый ссылочный механизм - не лучший способ управлять и закрывать объекты Statement и ResultSet.
источник
Я добавляю еще немного понимания.
Войдите в систему как sysdba.
В Putty (вход в Oracle):
В SqlPlus:
UserName:
sys as sysdba
Установите значение session_cached_cursors на 0, чтобы у него не было закрытых курсоров.
Выберите существующий набор значений OPEN_CURSORS для каждого соединения в БД
Ниже приведен запрос на поиск списка SID / соединений с открытыми значениями курсора.
Используйте приведенный ниже запрос, чтобы определить sql в открытых курсорах.
Теперь отлаживайте код и наслаждайтесь !!! :)
источник
Исправьте свой код следующим образом:
Вы уверены, что действительно закрываете свои pStatements, соединения и результаты?
Для анализа открытых объектов вы можете внедрить шаблон делегатора, который обертывает код вокруг ваших объектов состояния, соединения и результатов. Так вы увидите, если объект будет успешно закрыт.
Пример для: pStmt = obj. getConnection () .prepareStatement (sql);
источник
Если ваше приложение представляет собой приложение Java EE, работающее на Oracle WebLogic в качестве сервера приложений, возможной причиной этой проблемы является настройка размера кэша инструкций в WebLogic.
Если параметр размера кэша инструкций для конкретного источника данных примерно равен или превышает значение максимального числа открытых курсоров базы данных Oracle, тогда все открытые курсоры могут использоваться кэшированными операторами SQL, которые открыты WebLogic, в результате чего в ошибке ORA-01000.
Чтобы решить эту проблему, уменьшите значение параметра Размер кэша инструкций для каждого источника данных WebLogic, указывающего на базу данных Oracle, чтобы он был значительно меньше, чем максимальное значение числа курсоров в базе данных.
В консоли администратора WebLogic 10 параметр размера кэша операторов для каждого источника данных можно найти в разделе Службы (слева)> Источники данных> (отдельный источник данных)> вкладка Пул соединений.
источник
Я тоже столкнулся с этой проблемой.
Я использовал Spring Framework с Spring JDBC для уровня dao.
Мое приложение каким-то образом пропускало курсоры, и через несколько минут оно выдавало мне это исключение.
После тщательной отладки и анализа я обнаружил, что проблема с индексированием, первичным ключом и уникальными ограничениями в одной из таблиц , используемых в запросе. i.
Мое приложение пыталось обновить ошибочно проиндексированные столбцы . Итак, всякий раз, когда мое приложение получало запрос на обновление индексированных столбцов, база данных пыталась выполнить переиндексацию на основе обновленных значений. Утечки курсоров .
Мне удалось решить проблему, выполнив правильную индексацию столбцов, которые использовались для поиска в запросе, и применив соответствующие ограничения везде, где это необходимо.
источник
Сегодня я столкнулся с той же проблемой (ORA-01000). У меня был цикл for в try {} для многократного выполнения оператора SELECT в базе данных Oracle (каждый раз при изменении параметра), а в finally {} у меня был код для закрытия Resultset, PreparedStatement и Connection как обычно , Но как только я достиг определенного количества циклов (1000), я получил ошибку Oracle о слишком большом количестве открытых курсоров.
Основываясь на сообщении Эндрю Алкока выше, я внес изменения так, что внутри цикла я закрыл каждый набор результатов и каждый оператор после получения данных и перед повторным циклом, и это решило проблему.
Кроме того, такая же проблема возникла в другом цикле вставки операторов в другой базе данных Oracle (ORA-01000), на этот раз после 300 операторов. Опять же, это было решено таким же образом, поэтому либо PreparedStatement, либо ResultSet, либо оба они считаются открытыми курсорами, пока они не будут закрыты.
источник
Вы установили autocommit = true? Если нет, попробуйте это:
источник
запрос на поиск открытого sql.
источник
Эта проблема в основном возникает, когда вы используете пул соединений, потому что, когда вы закрываете соединение, это соединение возвращается в пул соединений, и весь курсор, связанный с этим соединением, никогда не закрывается, поскольку соединение с базой данных все еще открыто. Таким образом, одна из альтернатив - уменьшить время простоя соединений в пуле, поэтому, когда соединение простаивает в течение, скажем, 10 секунд, соединение с базой данных будет закрыто, и новое соединение будет создано для помещения в пул.
источник
Использование пакетной обработки приведет к меньшим накладным расходам. Примеры см. По следующей ссылке: http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm
источник
В нашем случае мы использовали Hibernate, и у нас было много переменных, ссылающихся на один и тот же отображаемый объект Hibernate. Мы создавали и сохраняли эти ссылки в цикле. Каждая ссылка открывала курсор и оставалась открытой.
Мы обнаружили это, используя запрос для проверки количества открытых курсоров при запуске нашего кода, переходя через отладчик и выборочно комментируя вещи.
Что касается того, почему каждая новая ссылка открывала другой курсор - рассматриваемый объект имел коллекции других объектов, сопоставленных с ним, и я думаю, что это как-то связано с ним (возможно, не только это само по себе, но в сочетании с тем, как мы настроили режим выборки и настройки кеша). В самом Hibernate были ошибки, связанные с невозможностью закрытия открытые курсоры, хотя, похоже, они были исправлены в более поздних версиях.
Поскольку нам в любом случае не нужно было иметь столько повторяющихся ссылок на одну и ту же сущность, решением было прекратить создавать и удерживать все эти избыточные ссылки. Однажды мы сделали эту проблему, когда отсутствовали.
источник
У меня была эта проблема с моим источником данных в WildFly и Tomcat при подключении к Oracle 10g.
Я обнаружил, что при определенных условиях оператор не закрывается даже при вызове statement.close (). Проблема заключалась в используемом нами драйвере Oracle: ojdbc7.jar. Этот драйвер предназначен для Oracle 12c и 11g и, похоже, имеет некоторые проблемы при использовании с Oracle 10g, поэтому я перехожу на ojdbc5.jar, и теперь все работает нормально.
источник
Я столкнулся с той же проблемой, потому что запрашивал db более 1000 итераций. Я использовал try и, наконец, в своем коде. Но по-прежнему возникала ошибка.
Чтобы решить эту проблему, я просто зашел в oracle db и выполнил следующий запрос:
ALTER SYSTEM SET open_cursors = 8000 SCOPE = BOTH;
И это сразу решило мою проблему.
источник