3

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

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检查的主体,暗示光标确实已关闭。然而,打开的游标数量似乎仍在增加!

4

1 回答 1

1

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

但是,我无法为此找到参考。有人可以备份吗?

于 2013-08-08T06:32:14.723 回答