3

这是场景...

我们有一个运行最新版本 ODAC(Oracle 客户端)的内部网站。它打开数据库连接,运行存储过程或打包方法,然后断开连接。连接池已打开,我们目前在我们的开发和测试环境中都是 11g 版本,但在我们的生产环境中是 10gR2。这发生在生产上。

几天前,一个进程开始触发 ORA-2020 错误。该过程是从我们内部网站上的网页调用的。用户只需设置一个日期,点击一个按钮,就可以在与网站分开的另一个系统上开始工作。然而,调用本身使用数据库链接来运行函数。

我们搜索了 SQL,发现它只使用了一个数据库链接。而且由于这些链接是基于每个会话的,并且用户没有超过默认限制 4,我们怎么可能收到 ORA-2020 错误。

我们已经运行了许多测试来尝试超过默认限制 4。据我回忆,ODAC 在每次连接后运行一次提交,我似乎无法运行 4 个 DB 链接,然后运行一段 SQL在出现任何错误后直接使用 1 个 DB 链接。我可以提出这个错误的唯一方法是,如果我运行一个带有 4 个 DB 链接的查询,然后是一个函数或一段动态 SQL,其中包含一个数据库链接。我们没有这个问题,因为这个问题是零星的。它并不总是发生。

问题

  1. 连接池是否有可能允许用户 B 在运行初始进程后使用用户 A 的连接,从而在用户 B 运行具有更多数据库链接的 SQL 语句时添加到打开的链接数?
  2. 这是我们应该将限制提高到 4 以上的情况吗?增加数量有什么坏处?
  3. 在断开与数据库的连接之前,我是否需要明确关闭打开的数据库链接?Oracle 文档似乎建议它应该自动发生,但“有时”......不会。
4

2 回答 2

2

首先,简单的解决方案:我会仔细检查生产数据库中默认链接的数量实际上是4。

select *
  from v$system_parameter
 where name = 'OPEN_LINKS'

假设你不会轻易下车:

连接池是否有可能允许用户 B 在运行初始进程后使用用户 A 的连接,从而在用户 B 运行具有更多数据库链接的 SQL 语句时添加到打开的链接数?

您说您明确关闭了会话,根据文档,这应该意味着与该会话关联的所有链接都已关闭。除此之外,我承认在这一点上完全无知。

这是我们应该将限制提高到 4 以上的情况吗?增加数量有什么坏处?

没有我能想到的缺点。尽管很久以前,Tom Kyte 建议每个打开的数据库链接使用 500k 的 PGA 内存。如果你没有,那么这显然会导致问题,但在大多数情况下应该没问题。

然而,有一些意想不到的后果:想象你把这个数字增加到 100。有人编写了一些代码,不断打开链接并通过所有链接select * from my_massive_table或类似链接获取大量数据。你有 100 个会话,而不是 4 个会话,它试图同时传输数百 GB。您的网络在压力下死亡...

可能还有更多,但你明白了。

在断开与数据库的连接之前,我是否需要明确关闭打开的数据库链接?Oracle 文档似乎建议它应该自动发生,但“有时”......不会。

正如您所注意到的,最好的答案是“可能不是”,这没有多大帮助。您没有确切提及您是如何终止会话的,但是如果您要杀死它而不是优雅地关闭它,那肯定是。

使用数据库链接会在远程服务器上生成一个子进程。因为您的服务器不再绝对负责此进程,所以有很多事情可能导致它成为孤立的或在父进程终止时无法关闭。这绝不会一直​​发生,但它可以而且确实如此。

我会做两件事。

  1. 在您的过程中,如果遇到异常,请将以下查询的结果通过电子邮件发送给您自己。

    select * 
      from v$dblink
    

    至少您将知道会话中打开了哪些数据库链接,并为您提供一些跟踪它们的方法。

  2. 遵循文件建议;具体如下:

    “您可能需要手动关闭链接。例如,在以下情况下关闭链接:

    • 通过链接建立的网络连接在应用程序中很少使用。
    • 必须终止用户会话。”

第一个似乎完全适合您的情况。除非您的流程是时间敏感的,但似乎并非如此,否则您会失去什么?语法是:

alter session close database link <linkname>
于 2012-04-04T20:31:23.780 回答
1

我们最终增加了链接数量,但我们从未找到根本原因。

于 2012-10-24T15:03:16.767 回答