如何在Oracle下处理大型事务?

我们的应用程序基于Hibernate 3.5,Spring 3.1和Oracle下我继续运行Max Cursors Exceeded问题,主要是在处理大型事务时(涉及的实体数量大,执行的查询数量)。 在H2,MS SQL Server或MySQL上运行应用程序时不会出现此类问题。

如果我正确理解了我的调查结果,Oracle会为事务中构建的每个ResultSet创建一个游标,这些游标只有在Connection上调用close (即Hibernate Session)时才会释放。

我的问题(现在):

  1. 在交易正在进行时,有没有办法让Oracle清理游标? 在事务中的特定点之后,有许多查询结果不需要,但Oracle似乎保持游标打开。
  2. 是否有“正常”的最大光标设置? 默认值为50,我们的大多数客户都设置了400-600个游标,但我见过的一些论坛post似乎表明几千个更常见。 当我们建议将最大游标数量增加到(例如)5000时,我们似乎也从我们的客户端DBA获得了很多回击。这真的是一个大问题吗?

坦率地说,我读过的大多数论坛帖都与ResultSet / Statement / Connection泄漏有关,但是根据我们的分析,我们没有它们; 当我们关闭连接时,当前光标计数恢复正常。 我们似乎是唯一一个在单个事务中尝试执行几百个操作的问题。 这真的是这个exception吗?

谢谢你的建议; 这些东西甚至使我的白发脱落

Oracle为每个结果集创建游标,并在关闭结果集时释放它(jdbc ResultSet.close()或类似的)。 对于任何设计良好的应用程序,每个会话默认50个开放游标就足够了(一旦我测量它,在生产模式下它从未超过20个)。

您应该检查如何在获取后使Hibernate关闭结果集。 一般来说,如果真的需要1000个开放游标,我无法想象会话应该做什么。 我从来没有看到max_open_cursors设置超过1000,所以,我想,这对于设计不良的应用程序来说也足够了(但是……在清醒的事实中没有完美的限制,我从不使用Hibernate)。

每个游标都意味着一些内存,因此增加max_open_cursors不是零价格的解决方法。

你会说你有某种资源泄漏。 99.99%的案例是由应用程序中的错误引起的。 你应该尽可能使用java7构建try-with-resources。 通常的方法如何调查这些问题是:

  • 从DBA请求SELECT_CATALOG_ROLE(这将使您可以访问v$ Oracle视图)
  • 在浪费资源的同时让应用程序运行
  • 通过select * from v$open_cursor;检查我们打开的游标select * from v$open_cursor; 。 如果你很幸运,你会得到每个泄漏光标的Sql查询。
  • 如果你没有使用hibernate,那么sql文本会直接指向你的源代码。 但是既然你使用了hibernate就可以猜到了。 实体经理有时候是不可预测的。

PS:游标就像JVM中的一个线程。 如果在“某些”虚拟机中执行某些代码,它就是一个地方。 您可以在单个连接上拥有多个游标。 关闭结果集时,光标关闭。 通过执行此操作,您告诉Oracle您不再关心来自SQL查询的任何其他行。 当然,当你关闭连接时,它的所有游标也都会被关闭。 但是,当您只需要关闭结果集时,请不要关闭连接。 打开新连接是非常详尽的任务。