Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何防止重复自动连接到Oracle数据库?_.net_Oracle_Database Connection_Connection Pooling_Dataprovider - Fatal编程技术网

.net 如何防止重复自动连接到Oracle数据库?

.net 如何防止重复自动连接到Oracle数据库?,.net,oracle,database-connection,connection-pooling,dataprovider,.net,Oracle,Database Connection,Connection Pooling,Dataprovider,背景 我们有一个C#/VB.net客户端应用程序,它使用连接到Oracle数据库的WCF服务。web服务使用.NET framework的Oracle数据提供程序(不要与ODP混淆)连接到数据库。我们的测试人员经历过零星的Oracle帐户锁定,这似乎是在更改用户的Oracle密码后不久发生的。dba_audit_跟踪日志显示,在没有任何用户或客户端活动的情况下,每隔很长的时间(即每两分钟一次)自动尝试连接。大量日志(IIS、WCF跟踪、消息日志等)已确认这些连接尝试不是由客户端应用程序直接启动的

背景

我们有一个C#/VB.net客户端应用程序,它使用连接到Oracle数据库的WCF服务。web服务使用.NET framework的Oracle数据提供程序(不要与ODP混淆)连接到数据库。我们的测试人员经历过零星的Oracle帐户锁定,这似乎是在更改用户的Oracle密码后不久发生的。dba_audit_跟踪日志显示,在没有任何用户或客户端活动的情况下,每隔很长的时间(即每两分钟一次)自动尝试连接。大量日志(IIS、WCF跟踪、消息日志等)已确认这些连接尝试不是由客户端应用程序直接启动的;它们必须独立于web服务或System.Data.OracleClient库内部。自动尝试将永远持续,直到web服务的工作进程(单个工作进程)因不活动而死亡

在某些情况下,这些自动尝试会在密码更改之前开始,并成功连接到数据库,但一旦密码更改,下一次尝试将因用户名/密码无效而失败。三次尝试后,帐户被锁定。我们正在试图找到这些周期性连接尝试的来源

我在甲骨文的论坛上发现了一个非常相似但尚未回答的问题

当前想法

我们最近的调查使我们相信这是连接池的意外行为。如果用户在密码更改之前连接到web服务,则会为原始连接字符串创建连接池。在更改密码并重新登录到web服务之后,数据提供者将基于新的连接字符串创建一个新的连接池

数据提供程序中是否有什么东西试图使第一个连接池中的旧连接保持活动状态?可能第一个连接池正在丢弃旧连接并尝试用新连接(使用现在无效的连接字符串)来补充它。这是什么原因造成的?注意:我们使用最小/最大池大小(0/100)的默认设置


我们不相信我们的代码直接试图从第一个连接池访问连接。用户的会话没有上一个会话密码的任何内存,因此不会使用旧的连接字符串引用第一个连接池。此外,我们的代码中没有任何内容可以解释我们看到的非常精确的连接间隔。

这可能会有所帮助

基本上,在第二个网页中,MSDN声明“一旦创建,连接池不会被破坏,直到活动进程结束。”。您的web服务可能保留了太多的连接/连接池,因此出现了一些问题

所以我的建议是:除了通过添加一些连接日志(可能只是一个文本文件)进行更多的故障排除,或者第一个链接有一个很好的命令来跟踪到数据库的连接之外,我现在会尝试关闭连接池。您似乎遇到的问题称为“池碎片”。这是一台通过连接池传输所有数据库连接的计算机的流量很大的地方。由于池太多,内存问题开始出现,连接没有正确关闭。第二个问题是您的问题,如果连接未关闭,或者假设您的密码更改命令在使用旧连接池的其他命令列表之前执行,那么您将遇到问题


最终,在您的情况下,您将拥有一个单点(web服务),它创建了自己的web连接池(不针对用户),并通过自己的连接将数据返回给用户。这意味着必须有不同类型的身份验证,由web服务端处理,以处理连接的用户。我相信现在您的模型中可能会有太多的更改,但我强烈建议您最终寻找解决方案。

每当发生任何会使连接无效的事件时,您需要销毁池,以便对任何泄漏的连接和/或池的保留进行适当标记,以防止重复使用。为此,您需要使用数据提供程序的
clearpool
clearallpools
方法


此外,全局异常管理器可以侦听为无效用户引发的异常,并通过枚举标识为连接字符串一部分的用户的连接来销毁该池。可能效率不高,但应该完成这项工作。

根本的问题最终是未释放的数据库连接。打开连接时,会将其签出连接池。如果连接从未关闭,则池认为它仍在使用。这会导致池管理逻辑使用原始连接字符串定期重新验证数据库。当密码更改时,这会很快导致登录尝试失败和帐户锁定

// Problem logic; connection is never closed/returned to the connection pool.
public static void ConnPoolTest1()
{
    OracleConnection conn = new OracleConnection(connectionStringWithPooling);
    conn.Open();

    //...Do some work

    // Sit on this line for 5-10 minutes and examine Oracle's dba_audit_trail.
    Console.ReadKey(); // Since connection was never released back to the connection pool, the
                       // data provider's pool management will regularly re-authenticate with DB.
                       // If user's password changes before this process dies (releasing the
                       // connection pools), you start accumulating failed password attempts.
}
解决此问题的正确方法是确保连接完成后始终返回到池中

// Best practice: ALWAYS CLOSE YOUR CONNECTIONS WHEN YOU ARE DONE!
public static void ConnPoolTest2()
{
    OracleConnection conn = new OracleConnection(connectionStringWithPooling);
    conn.Open();

    //...Do some work

    conn.Close();

    // Sit on this line for 5-10 minutes and examine Oracle's dba_audit_trail.
    Console.ReadKey(); // No problem here! No recurring authentication attempts because the
                       // connection has been returned to the pool.
}

注意:其他答案建议在密码更改时关闭池并清除旧的连接池。在我们搜索未发布的资源时,这些建议对我们起到了临时补丁的作用,它们极大地帮助我们隔离了问题。

您可能想转移到,但现在似乎是web服务方面的问题。我希望dba.stackexchange用户能把我指回到这里!我同意我们最终会有很多池,特别是当测试人员反复执行更改时