【问题标题】:ORA-01000: maximum open cursors exceeded using oracle instant client and C#ORA-01000: 使用 oracle 即时客户端和 C# 超出最大打开游标
【发布时间】:2015-04-26 02:51:41
【问题描述】:

我们的 C# 应用程序正在生成 ORA-01000 错误。我们使用的是 ODP.Net,应用程序运行得非常完美,没有任何 ORA-01000 错误。

我们删除了 ODP.Net 并安装了即时客户端(我们现在使用 7 个 dll 文件从 C# 连接到 Oracle,它们是 oci.dll、ociw32.dll、Oracle.DataAccess.dll、orannzsbb11.dll 和 oraocci11。 dll、oraociicus11.dll 和 OraOps11w.dll)。

从那时起,我们在执行具有多个查询的长流程时得到了 ORA-01000。注意我们正在关闭/释放 OracleDataReader 对象。

带有即时客户端的 ORA-01000 背后的原因可能是什么?

【问题讨论】:

  • 那么一定有游标泄漏的地方。删除代码直到它消失,然后逐步添加。
  • 您好 OldPragrammer,感谢您的快速回复。你能详细说明一下吗?

标签: c# oracle


【解决方案1】:

使用此查询检查打开游标的限制:

SELECT NAME, VALUE DISPLAY_VALUE, ISDEFAULT
FROM V$PARAMETER
WHERE NAME = 'open_cursors';

在我看来,默认值是 50,这是相当低的。 见文档:OPEN_CURSORS

要求您的 DBA 增加它,根据文档,将此值设置为高于实际需要的值不会增加开销。

我刚刚检查了我的数据库

SELECT COUNT(*), user_name 
FROM V$OPEN_CURSOR
WHERE user_name = 'SYS'
GROUP BY user_name;

640 个打开游标仅由 SYS(一个会话中的峰值 113)引起,即不是由我的(可能是坏的)应用程序引起的。

【讨论】:

  • 对于像我这样的 Oracle 新手来说,这些查询非常有用。谢谢。
  • 为了清楚起见,OPEN_CURSORS 参数适用于每个会话。系统范围的值不受限制。
【解决方案2】:

我知道这个问题已经有一年了,但我们刚刚遇到了同样的问题。我们所有与 Oracle 相关的对象都已关闭和处置,但游标仍然泄漏。

问题似乎在于 ODP.Net 如何使用连接池。连接池默认开启,在我们的环境中,这似乎始终会导致游标泄漏,这种情况反复发生,直到数据库认为足够了并拒绝再授予。

解决方法是在连接字符串中禁用连接池,如下所示:

Data Source=myOracle;User Id=myUsername;Password=myPassword;Pooling=False;

我们的应用程序在启动时使用了 30 多个游标,并稳步增加到 200 个。现在禁用连接池后,它使用了 2 到 3 个游标。

【讨论】:

  • 谢谢!我遇到了同样的问题,您的解决方案有效!我有一个小应用程序,它进行了大量的存储过程调用,并且我到处都“使用”来正确处理对象。托管客户端似乎存在导致泄漏的错误。
【解决方案3】:

在我们公司,我们已经为这个问题苦苦挣扎了将近两个星期。所有一次性用品都已正确释放,但没有帮助:ORA-01000 问题仍然存在。

突然我们意识到:在一些调用非常频繁的存储过程中,执行了如下代码:dbms_sql.open_cursor

这个函数的危险之处在于它创建了一个新的游标,该游标只有句柄以数字的形式返回。离开范围后,Oracle 无法识别出这个数字后面有句柄,必须释放。结果是每次调用dbms_sql.open_cursor 时都会创建一个新游标,只要会话处于活动状态,它就会保持打开状态。由于我们使用的是会话池,因此这些游标会在很长一段时间内保持打开状态。

希望这个提示有所帮助。

【讨论】:

    【解决方案4】:

    Oracle 文档记录了有关 ORA-01000 的信息:

    ORA-01000 超出最大打开游标数

    原因:宿主语言程序试图打开过多的游标。初始化参数 OPEN_CURSORS 决定了每个用户的最大游标数。

    行动:修改程序以使用更少的游标。如果经常出现这个错误,关闭Oracle,增加OPEN_CURSORS的值,然后重启Oracle。

    在我的例子中,它是非托管资源,例如 OracleCommand、OracleRefCursor、OracleGlobalization 和 OracleDataReader。为了尽量减少打开的服务器游标的数量,显式处理 OracleCommand、OracleRefCursor、OracleGlobalization 和 OracleDataReader 对象。

    【讨论】:

    • 嗨 michaos,我尝试显式处理,但仍然没有关闭光标...
    • 不看源代码就很难说出具体的东西(尤其是在问答模式下)。无论如何,用简短的例子(可能)测试这些“微妙”的时刻是有意义的
    • ceodev 我也遇到了这个问题。在我的代码中,OracleCommand、OracleDataReader 和 OracleGlobalization 对象正在对它们进行“处理”,但我认为因为它们所在的对象没有超出范围,所以它永远不会被垃圾收集。无论如何,我通过创建一次 Oracle 对象对象并每次重新使用它们而不是使用 new 关键字解决了这个问题。
    【解决方案5】:

    ORA-01000 的唯一原因是打开的游标太多:)

    检查V$OPEN_CURSOR 视图并查看哪些游标处于打开状态。知道了它,您就可以确定它们为什么仍然打开。

    【讨论】:

    • 我已经在检查 V$OPEN_CURSOR 以查看打开游标的数量,但是我最初的问题是为什么它们没有被关闭!!!???
    • @ceodev 您的 dispose 代码可能没有您想象的那么可靠。你在用using吗?
    • 这是开发人员的问题。客户端应用程序负责关闭游标。
    • 伯爵不会给你任何东西。查看打开的游标的 sql 文本,看看它应该在哪里关闭以及为什么不关闭。
    • 嗨 Luaan,是的,我正在使用“使用”
    【解决方案6】:

    问题是由一些游标打开但未关闭引起的。

    两个问题可能会导致它(至少我看到的是这样)。存储过程中的某些显式打开的游标或 .Net 应用程序中未关闭的 DataReader。

    【讨论】:

      【解决方案7】:

      遇到了同样的问题,解决了

      OracleConnection.ClearPool(oraConn);

      在您的多个请求之间

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-14
        • 2015-03-29
        • 1970-01-01
        • 2017-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-24
        相关资源
        最近更新 更多