以下是场景。。。
我们有一个内部网站,正在运行最新版本的ODAC(Oracle客户端)。它打开数据库连接,运行存储过程或打包方法,然后断开连接。连接池已经打开,我们目前在开发和测试环境中都处于11g版本,但在生产环境中处于10gR2版本。这种情况发生在Production上。
几天前,一个进程开始引发ORA-2020错误。该过程是从我们内部网站上的网页调用的。用户只需设置日期,点击按钮,就可以在与网站分离的另一个系统上启动作业。然而,调用本身使用数据库链接来运行函数。
我们搜索了SQL,发现它只使用了那一个数据库链接。由于这些链接是基于每个会话的,并且用户没有超过默认限制4,我们怎么可能收到ORA-2020错误。
我们已经运行了许多测试,试图突破默认限制4。据我回忆,ODAC在每次连接后都会运行一个提交,我似乎无法运行4个DB链接,然后直接运行一个带有1个DB链接的SQL,但没有任何错误。我能提出这个错误的唯一方法是,如果我运行一个带有4个数据库链接的查询,然后运行一个函数或一段带有数据库链接的动态SQL。我们没有这个问题,因为这个问题是偶发的。这种情况并不总是发生。
问题
- 连接池是否允许用户B在运行初始进程后使用用户A的连接,从而在用户B运行具有更多数据库链接的SQL语句时添加到打开的链接数中
- 这是一种我们应该将上限提高到4以上的情况吗?增加数字有什么缺点
- 在断开与数据库的连接之前,是否需要显式关闭打开的数据库链接?Oracle文档似乎建议它应该自动发生,但"偶尔"。。。没有
首先,简单的解决方案:我会仔细检查生产数据库中默认链接的数量实际上是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文档似乎建议自动发生,但"偶尔"。。。没有。
正如你所指出的,最好的答案是"可能不会",这并没有多大帮助。你没有确切地提到你是如何终止会话的,但如果你要终止会话,而不是优雅地结束会话,那么肯定是这样。
使用数据库链接会在远程服务器上生成一个子进程。因为您的服务器不再完全负责这个进程,所以有很多事情可能会导致它成为孤立的,或者在父进程终止时无法关闭。这种情况绝不会一直发生,但它可以而且确实会发生。
我会做两件事。
在您的过程中,如果遇到异常,请将以下查询的结果通过电子邮件发送给您自己。
select * from v$dblink
至少您会知道会话中打开了哪些数据库链接,并提供了一些跟踪它们的方法。
遵循文件建议;具体如下:
"您可能需要手动关闭链接。例如,关闭链接时:
- 由链路建立的网络连接在应用程序中很少使用
- 必须终止用户会话。"
第一个似乎完全适合你的情况。除非你的过程对时间敏感,但事实并非如此,否则你会失去什么?语法为:
alter session close database link <linkname>
我们最终增加了链接数量,但我们从未找到根本原因。