Почему в этом пакете отсутствуют открытые курсоры?

В нашем приложении мы вызываем различные хранимые процедуры, которые возвращают ссылочные курсоры следующим образом:

SELECT foo_package.sp_Bar('arg1', 'arg2', 'arg3', 'arg4') FROM dual;

Функция wrap_xml преобразует результат курсора в тип XML, который затем будет использоваться в приложении. После преобразования он немедленно закрывает курсор (этот шаг решил для нас проблемы с памятью до).

FUNCTION wrap_xml (c_result SYS_REFCURSOR)
  RETURN XMLTYPE
IS
  xml_val   XMLTYPE;
BEGIN
  xml_val := xmltype.CreateXML (c_result);

  IF c_result%ISOPEN
  THEN
     CLOSE c_result;
  END IF;

  RETURN xml_val;
END;

В большинстве случаев это работает нормально: создается XML, а курсоры закрываются. Однако с момента введения хранимой процедуры, которая открывает курсор для динамического запроса, мы наблюдаем быстрое увеличение числа открытых курсоров, что в конечном итоге приводит к:

ORA-01000: maximum open cursors exceeded

Динамический запрос построен для «имитации» результатов, возвращаемых другими курсорами, в целях тестирования. Например, хранимая процедура создаст динамический запрос, подобный этому:

SELECT '1' as "COLUMN1", '990' as "COLUMN2", 'N' as "COLUMN3", NULL as "COLUMN5" FROM dual;

Затем он откроет курсор для этой строки запроса и вернет курсор:

OPEN rc_return FOR v_sql_query;
RETURN rc_return;

Результирующий ссылочный курсор снова передается в функцию wrap_xml выше, которая, как я ожидал, закроет курсор - точно так же, как и любой другой курсор. Однако, похоже, это не так, поскольку количество открытых курсоров продолжает расти. Что могло быть причиной этого?


Дополнительное расследование:

Проходя через функцию wrap_xml, я вижу, как поток программы пропускает тело проверки c_result%ISOPEN, подразумевая, что курсор действительно был закрыт. Тем не менее, похоже, что количество открытых курсоров все еще увеличивается!


person Stephan    schedule 29.07.2013    source источник
comment
Повторение тестов Винсента из вашего предыдущего вопроса, но с вашим v_sql_str в функции ret_cursor, у меня работает нормально, с 11gR2. Было бы интересно посмотреть, не сработает ли это для вас в 10g (?). Если этого не происходит, возможно, происходит что-то еще. Если да, то, возможно, это продолжение той же очевидной ошибки - вы сообщили об этом в Oracle?   -  person Alex Poole    schedule 29.07.2013
comment
А как насчет вашего приложения для звонков? Правильно ли закрывает соединения?   -  person OldProgrammer    schedule 03.08.2013
comment
@AlexPoole: Я еще не сообщил о возможной ошибке в Oracle, так как я все еще пытаюсь найти идентификатор службы поддержки моей компании.   -  person Stephan    schedule 03.08.2013
comment
@OldProgrammer: соединения с базой данных закрыты правильно. Более того, проблема с максимальным курсором не возникает, если мы закомментируем динамическую часть запроса этой функции.   -  person Stephan    schedule 03.08.2013


Ответы (1)


Похоже, мы устранили утечку, удалив проверку ISOPEN из функции wrap_xml и просто выполнив команду курсора закрытия во всех случаях. Очевидно, флаг ISOPEN не установлен на курсорах, открытых для динамических SQL-запросов.

Однако я не могу найти ссылку на это. Кто-нибудь может это подтвердить?

person Stephan    schedule 08.08.2013