Oracle 快速连接故障转移不适用于 ODP.NET。获取连接请求超时错误

Posted

技术标签:

【中文标题】Oracle 快速连接故障转移不适用于 ODP.NET。获取连接请求超时错误【英文标题】:Oracle Fast Connection Failover not working for ODP.NET. Getting Connection Request Timeout Error 【发布时间】:2020-10-09 04:56:45 【问题描述】:

我将 ODP.NET 用于我的 MVC 项目,并且当数据库关闭然后再次恢复时,不断收到“-1000 连接请求超时错误”。一旦我回收 IIS AppPool,它就会开始工作。我尝试在 catch 块内使用 ClearAllPool()、ClearPool(connection) 来删除错误连接,但两者都不起作用。我在 *** 上找到了一篇文章,通过在连接字符串中添加 HA events=true 来使用快速连接故障转移。我也试过了,但没有运气。我问过 DBA,他们说默认情况下该功能在服务器端。我不知道为什么即使数据库已启动并正在运行,ODP.NET 仍在使用在数据库关闭时创建的旧的无效连接?我的所有代码也都包装在一个 using 块中,该块将关闭/处理连接。我的 Oracle.DataAccess 版本是 12.1.0。我阅读了谷歌上关于连接池、FCF 的每一页,但没有任何帮助。

我的连接字符串如下:

<add name="XXX"; providerName="Oracle.DataAccess.Client"; connectionString="DataSource=XXX;username=xxx;password=XXX;Pooling=True;Connection Timeout=120; Connection LifeTime=120; Validate Connection=True; Min Pool size=1;Max Pool size=180; HA events=true; Incr Pool size=5; Decr Pool size=2;"/>

这是我的 oracle 连接代码:

using(OracleConnection conn= new OracleConnection(connectionstring))

    try
   
      OracleCommand cmd=new OracleCommand("storedprocedure",conn) 
      CommandType=CommandType.StoredProcedure;
      //add parameters to command
        foreach(var parmeter in parameters)
        
        cmd.Parameters.Add(parameter);
        
        conn.Open(); // this is where exception occurs

        cmd.ExecuteNonQuery();

    
   catch(OracleException ex)
   
     if(conn.State=ConnectionState.Open)
     
      conn.Close();
      conn.Dispose();
     

     //log exception ex in logfile

   

      if(conn.State=ConnectionState.Open)
      
       conn.Close();
       conn.Dispose();
      

//Dispose All Parameters using Dispose() outside using statement.
foreach(var parmeter in parameters)
parameter.Dispose();


唯一的解决方案是当我设置 Pooling=False 时,我们不想这样做。

我使用了这些连接字符串属性,例如增加最小池大小、增加连接生命周期等,但似乎没有任何效果。

我将非常感谢这里的任何帮助。

谢谢。

【问题讨论】:

在您的连接池设置中是否有一个选项可以在使用连接之前测试连接(通常使用简单的查询,例如“select 1 from dual;”)?您尝试使用的 HA 功能仅在您有备用实例可以故障转移到的 Oracle RAC 配置中有效。在数据库实际上完全关闭的情况下,它们将无济于事。死连接通常必须由连接池检测和管理/重置,如果数据库关闭,则需要丢弃并重新连接。连接无法在数据库重新启动后继续存在。 感谢您的回复。不,我没有设置在使用之前测试连接。很抱歉,但此设置有什么帮助? 在将连接检出到应用程序之前将连接池设置为测试连接可确保在应用程序尝试使用它们之前识别出损坏的连接。这是大多数池的共同特征。除非您尝试将其用于某事,否则无法识别到 Oracle DB 的死连接,因此连接池识别坏连接、丢弃它们并替换它们以保持最小数量的可行连接非常重要。通常有一些设置可以启用测试、指定测试连接的频率、测试查询以及要维护的最小连接数。 如果您的数据库关闭/重新启动,那么您的所有连接都将中断,必须丢弃和更换。具有上述功能的连接池将不断尝试创建所需的最小连接数,直到成功,一旦恢复联机,就会自动登录回数据库。根据中断时间的长短和您的应用程序对延迟获取有效连接线程(以及数据库离线时可能中断的事务)的容忍度,这可能使您的应用程序能够以对最终用户透明的方式重新启动。 我认为这对我来说非常有意义。我将在我的代码中添加连接测试并检查它是否有效。再次感谢您的详细解释。 【参考方案1】:

试试这个,如果你还有这个问题告诉我

using(OracleConnection conn= new OracleConnection(connectionstring))
using(OracleCommand cmd=new OracleCommand("storedprocedure",conn))

    cmd.CommandType=CommandType.StoredProcedure;
    foreach(var parmeter in parameters)
    
        cmd.Parameters.Add(parameter);
    
    conn.Open(); // this is where exception occurs
    cmd.ExecuteNonQuery();

如果不希望出现错误,则将整个块放入try/catch

【讨论】:

非常感谢。这个解决方案对我有用。我按照您的建议将 cmd 包含在单独的 using 语句中,并且它有效。这是否意味着我之前代码中的第一个“using”语句没有正确处理 oracle 命令? @Dan 您已处理连接但未处理命令。命令保持连接。您的代码序列不是最佳的。要回答这个问题,您需要反映 Oracle 数据访问 dll。我以前做过,学到了很多。 我现在明白了。非常感谢你的帮助。你节省了很多时间。我们试图找到一个解决方案很多天。实际上,今天,我发现我的一位同事在数据库出现故障并恢复时没有收到连接超时错误。他的代码序列与我没有配置 cmd 的代码序列相同。我们唯一的区别是他使用的是 Oracle 12.2,而我使用的是 12.1。我不明白 12.2 中发生了什么变化,如果 cmd 没有正确处理是可以的。我做了一些研究,但没有找到任何东西。会继续研究。但感谢您的解决方案。效果很好。

以上是关于Oracle 快速连接故障转移不适用于 ODP.NET。获取连接请求超时错误的主要内容,如果未能解决你的问题,请参考以下文章

集群环境中的故障​​转移不适用于 JSF 2、Richfaces 4、Tomcat 7

ActiveMQ rebalanceClusterClients 不适用于 Spring Boot JMS

Broadcom 网卡绑定的几种模式(翻译)

2012故障转移群集的搭建(本人小白)

在 Wildfly-17 中的数据库故障转移期间回滚事务时,数据库连接不会从池中删除

oracle数据库的优势都有哪些?