为什么这个软件包泄漏了游标?

时间:2013-07-29 08:42:58

标签: oracle plsql cursor dynamic-queries

在我们的应用程序中,我们调用以下列方式返回引用游标的各种存储过程:

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

wrap_xml函数的作用是将游标结果转换为XML类型,然后将在应用程序中使用。转换后,它会立即关闭光标(此步骤有solved memory issues for us before)。

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检查的主体,暗示光标确实已经关闭。然而,看起来开放光标数仍然增加!

1 个答案:

答案 0 :(得分:1)

我们似乎已经通过从ISOPEN函数中删除wrap_xml检查并在所有情况下只执行close cursor命令来堵塞泄漏。显然,在为动态SQL查询打开的游标上没有设置ISOPEN标志。

但是,我无法为此找到参考。任何人都可以支持吗?