ODP.NET Oracle.ManagedDataAcess 随机 ORA-12570 错误

Posted

技术标签:

【中文标题】ODP.NET Oracle.ManagedDataAcess 随机 ORA-12570 错误【英文标题】:ODP.NET Oracle.ManagedDataAcess random ORA-12570 errors 【发布时间】:2016-05-22 23:31:54 【问题描述】:

我正在尝试从非托管版本迁移到 Oracle.ManagedDataAcess 并接收随机 ORA-12570 TNS:packet reader failure。

我不知道为什么会出现这个错误,但是一旦开始,每个后续请求都会在大约 10-30 分钟内给出相同的错误,然后再运行 10-30 分钟,以此类推。

所以这是一个随机的后续失败一段时间然后后续成功

已经尝试了很多东西,重新开始:

环境:

Oracle.ManagedDataAcess 版本 12.1.2400 (4.121.2.20150926) (nuget)(服务器上未安装可能覆盖 bin 版本的 gac 参考) Oracle Server Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production Windows 2012(Windows 更新正常)

已检查:

防火墙:不是防火墙问题 机器错误:同样的问题发生在我的机器、Azure WebApp 和 AWS EC2 实例上 干扰:没有运行嗅探器、透明代理等。 加密:我不使用任何类型的加密(除非默认启用了我不知道的加密) 连接字符串:相同的连接字符串与非托管版本完美配合

其他信息:

这是一个生产数据库,非常稳定 应用编译到anycpu,IIS应用池限制为64bits 我每次都测试完全相同的请求(只是刷新一个rest ws,webapi的get url),所以它与数据格式无关

配置:

服务器 sqlnet.ora

SQLNET.AUTHENTICATION_SERVICES= (NTS) NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)

应用程序 Web.config

<connectionStrings>
<add name="XXXX" connectionString="Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=xxx.xxx.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=xxx)));User Id=xxxxx;Password=xxxxx;" />
</connectionStrings>

<configSections>
    <section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</configSections>

<oracle.manageddataaccess.client>
    <version number="*">
      <dataSources>
        <!--<dataSource alias="SampleDataSource" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) " />-->
      </dataSources>
      <settings>
        <setting name="SQLNET.AUTHENTICATION_SERVICES" value="NONE"/> <!--NTS-->
        <setting name="sqlnet.crypto_checksum_server" value="rejected"/>
        <setting name="sqlnet.crypto_checksum_client" value="rejected"/>
        <setting name="SQLNET.ENCRYPTION_SERVER" value="rejected"/>
      </settings>
    </version>
</oracle.manageddataaccess.client>

一些参考资料:

https://community.oracle.com/thread/3634263?start=0&tstart=0

ODP.net managed driver throws ORA-12570: Network Session: Unexpected packet read error

Managed Oracle Client with Oracle Advanced Security Options

ODP.NET error in IIS: ORA-12357 Network Session End of file

更新 1

在池更改后(正如我在这里描述的答案),我决定发布一个版本来做一些真正的测试。 1 天后,用户抱怨性能我得到另一个错误:值不能为空。参数名称:字节数组

我将引用改回非托管版本,一切又恢复正常,速度更快,没有字节数组错误,更好的池管理。

所以我现在只是放弃托管版本,也许我会在 Oracle 下一个版本上再试一次。

如您所见,这里有一些关于这个新错误的参考,看起来像是另一个错误(仍然没有任何答案)。

https://community.oracle.com/thread/3676588?start=0&tstart=0

EF + ODP.NET + CLOB = Value Cannot be Null - Parameter name: byteArray?

到目前为止,不使用的原因:

池管理错误 CLOB null/not null bytearray 错误 性能下降可能与池错误有关

【问题讨论】:

很详细的问题,好!您可以尝试在连接字符串中使用“Pooling=False”吗?我怀疑你的连接池有问题 @bdn02 好的,我刚刚更改为 Pooling=false,现在我将等待错误再次发生。谢谢! 同时检查数据库端的 ALERT 日志是否有错误。然后,研究并解决这些问题...... 解决了吗? 2016年我仍然得到这个!相同的组件(Oracle 托管数据访问)。 @SuperJMN 还没有。 NuGet 上的最后一个版本还是一样: 上次发布时间:2015-10-14 |最新版本:12.1.2400 【参考方案1】:

根据我对类似错误 12570(读取器与写入器)的经验,此错误只有一个原因 - 您的网络上的某些东西正在终止空闲的 tcp 连接。通常这是一个防火墙/托管交换机。你说你已经排除了防火墙,但我不确定如何。 db 本身可能正在终止连接(dba 脚本),但我记得这是一个不同的错误。

Ora-12571 可能略有不同。但是,既然您已经确定问题是相同的,因为它是长期建立的池连接,我将继续进行。

你可以做几件事:

    在连接字符串中设置最小池大小 = 0。这通常为我解决问题。它允许在应用程序空闲时关闭整个池。但是,如果您的流量剧烈波动,则可能需要增加 decr 池的大小,以便更快地关闭由疯狂高峰创建的连接。 在 sqlnet.ora 中设置 Expire_Time。顾名思义,这个设置发送一个探测包,这会导致任何 tcp 空闲监控得到满足。这里唯一的问题是我不完全确定如何使用托管提供程序设置 sqlnet 设置。我猜 sqlnet.ora 可以进入 exe 目录,但我也看到一些迹象表明它可以在 .config 中以以下形式设置(参见类似的 wallet_override 示例here)因为你只是在托管提供程序中得到这个,我想知道你的非托管客户端 sqlnet.ora 是否已经有这个设置。

多年来我已经多次看到这种情况,第一次发生这种情况时,我创建了一个实用程序,该实用程序基本上执行二进制搜索,通过创建不同持续时间的连接来确定确切的超时时间。如果它始终在相同的终止时间着陆,您可以猜测某处有一个设置导致了这种情况。如果它不稳定,那么您可能有某种基础设施脆弱性。

不幸的是,我将它创建为一个 c# 表单应用程序,所以我将表单代码和设计器代码都粘贴在下面:

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Oracle.ManagedDataAccess.Client;

namespace TimeoutTest

  public partial class Form1 : Form
  
    List<TestConnection> connections;
    Int32 connectionCount;
    Int32 multiplier;
    Int32 initialConnectionWait;

    TestConnection controlConnection = null;

    public Form1()
    
      InitializeComponent();



    

    private void BtStart_Click(object sender, EventArgs e)
    

      connectionCount = Int32.Parse(InConnections.Text);
      multiplier = Int32.Parse(InMultiplier.Text);
      initialConnectionWait = Int32.Parse(InInitialWait.Text);

      DisplayMessage("Starting control connection\r\n");
      controlConnection = new TestConnection();
      controlConnection.ErrorOccured += new EventHandler(controlConnection_ErrorOccured);
      controlConnection.IsControlConnection = true;
      controlConnection.StartTest(2);

      connections = new List<TestConnection>();
      DisplayMessage("Spinning up 0 connections...\r\n", connectionCount);
      for (int i = 0, idleTime=initialConnectionWait; i < connectionCount; i++, idleTime*=multiplier)
      

        TestConnection connection = new TestConnection();
        connection.Notified += new TestConnection.NotificationEventHandler(connection_Notified);
        connection.ErrorOccured += new EventHandler(connection_ErrorOccured);
        connection.TestCompleted += new EventHandler(connection_TestCompleted);
        connection.StartTest(idleTime);

        connections.Add(connection);
      
      DisplayMessage("");
    


    void controlConnection_ErrorOccured(object sender, EventArgs e)
    
      DisplayMessage("\r\nControl connection error, aborting!!!");
      BtCancel_Click(this, EventArgs.Empty);

    

    void connection_TestCompleted(object sender, EventArgs e)
    
      TestConnection currentConnection = (TestConnection)sender;
      
      if (currentConnection == connections.Last())
        DisplayMessage("\r\nAll tests complete.  Done");
      
    

    void connection_ErrorOccured(object sender, EventArgs e)
    
      //stop any active connection.
      foreach(TestConnection tc in connections)
      
        tc.CompletionTimer.Enabled=false;
      

      TestConnection currentConnection = (TestConnection)sender;
      Int32 upperTime = currentConnection.IdleTime;
      Int32 lowerTime = 0;
      
      Int32 index = connections.IndexOf(currentConnection);
      //if this is not the first connection...
      if(index > 0)
      
        //...then set the lower time based on the previous connection
        lowerTime = connections[index-1].IdleTime;
      

      //get the difference between the lower and upper as the new range to work on
      Int32 range = upperTime - lowerTime;

      
      //divide the range over the number of connections to get the new interval
      Int32 interval = range / this.connectionCount;
      connections.Clear();

      //if the interval is too small try to reduce the number of connections
      while (interval < 2 && this.connectionCount > 2)
      
        this.connectionCount--;
        DisplayMessage("\r\nConnections too high for current resolution.  Reducing to 0 connections.", this.connectionCount);
        interval = range / this.connectionCount;
      



      if(interval < 2)
      
        DisplayMessage("\r\nResolution cannot be increased.  Done.");
      
      else
      
        DisplayMessage("\r\nRestarting test with min:0, max1, resolution2.", lowerTime, upperTime, interval);


        //create the new connections
        for (int i = connectionCount-1, idleTime = upperTime-interval; i >= 0; i--, idleTime-=interval)
        

          TestConnection connection = new TestConnection();
          connection.Notified += new TestConnection.NotificationEventHandler(connection_Notified);
          connection.ErrorOccured += new EventHandler(connection_ErrorOccured);
          connection.TestCompleted += new EventHandler(connection_TestCompleted);
          connection.StartTest(idleTime);

          connections.Insert(0,connection);
        
        this.connectionCount = connections.Count;
      

    
    private void BtCancel_Click(object sender, EventArgs e)
    
      //stop any active connection.
      foreach (TestConnection tc in connections)
      
        tc.CompletionTimer.Enabled = false;
        tc.Command.Connection.Close();
      
      DisplayMessage("Stopped running tests.");
    


    void connection_Notified(object o, Form1.TestConnection.NotificationEventArgs e)
    
      DisplayMessage(e.Message);
    

    private void DisplayMessage(String message)
    
      DisplayMessage("0", message);
    
    private void DisplayMessage(String message, params Object[] args)
    
      OutStatus.AppendText(String.Format(message, args) + "\r\n");
    
    

    public class TestConnection
    
      public Boolean IsControlConnection  get; set; 
      public OracleCommand Command  get; private set; 
      public Timer CompletionTimer  get; private set; 
      public String ConnectionId  get; private set; 
      public Int32 IdleTime
      
        get
        
          return CompletionTimer.Interval / 1000;
        
        set
        
          CompletionTimer.Interval = value * 1000;
        
      
      #region Events and Delegates
      public event EventHandler ErrorOccured;
      public event EventHandler TestCompleted;
      public class NotificationEventArgs : EventArgs
      
        public NotificationEventArgs(String message)
        
          this.Message = message;
        
        public String Message  get; set; 
      

      public delegate void NotificationEventHandler(object o, NotificationEventArgs e);

      public event NotificationEventHandler Notified;

      private void Notify(String message)
      
        if (Notified != null)
        
          Notified(this, new NotificationEventArgs(message));
        
      
      public void Notify(String format, params object[] args)
      
        this.Notify(String.Format(format, args));
      



      #endregion

      public TestConnection()
      
        CompletionTimer = new Timer();
        CompletionTimer.Tick += new EventHandler(CompleteTest);

        Command = new OracleCommand(
          "select 'saddr:' || saddr || '-sid:' || sid || '-serial#:' || serial# || '-audsid:' || audsid || '-paddr:' || paddr || '-module:' || module  from gv$session where audsid=Userenv('SESSIONID')");

        Command.Connection = new OracleConnection(Configuration.OracleConnectionString);
      

      public String StartTest(Int32 idleTime)
      
        Command.Connection.Open();
        ConnectionId = (String)Command.ExecuteScalar();
        Notify("Started test with idle time=0, id=1.", idleTime, ConnectionId);
        IdleTime = idleTime;
        CompletionTimer.Enabled = true;
        return ConnectionId;
      

      private void CompleteTest(object sender, EventArgs e)
      
        if (!IsControlConnection)
          CompletionTimer.Enabled = false;
        try
        
          Command.ExecuteScalar();
          Notify("Test complete on connection with idle time=0, id=1.", IdleTime, ConnectionId);
          if (TestCompleted != null)
            TestCompleted(this, EventArgs.Empty);
        
        catch (OracleException ex)
        
          if (ex.Number == 12571)
          
            if (ErrorOccured != null)
            
              Notify("Found error on connection with idle time=0, id=1.", IdleTime, ConnectionId);
              ErrorOccured(this, EventArgs.Empty);
            
          
          else
          
            Notify("Unknown error occured on connection with timeout 0, Error: 1, \r\n2",(IdleTime).ToString(), ex, ConnectionId);

          
        
        catch (Exception ex)
        
          Notify("Unknown error occured on connection with timeout 0, Error: 1, \r\n2", (IdleTime).ToString(), ex, ConnectionId);
        
        finally
        
          if(!IsControlConnection)
            Command.Connection.Close();
        
      
    

    private void InConnections_TextChanged(object sender, EventArgs e)
    
      Int32.TryParse(InConnections.Text,out connectionCount);
      Int32.TryParse(InMultiplier.Text,out multiplier);
      Int32.TryParse(InInitialWait.Text, out initialConnectionWait);

      OutLongestConnection.Text = (Math.Pow(multiplier,connectionCount-1) * initialConnectionWait).ToString();
    

    private void Form1_Load(object sender, EventArgs e)
    
      InConnections_TextChanged(this, EventArgs.Empty);
    

 

Form1.designer.cs:

namespace TimeoutTest

  partial class Form1
  
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    
      if (disposing && (components != null))
      
        components.Dispose();
      
      base.Dispose(disposing);
    

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    
      this.BtStart = new System.Windows.Forms.Button();
      this.OutStatus = new System.Windows.Forms.TextBox();
      this.InConnections = new System.Windows.Forms.MaskedTextBox();
      this.label1 = new System.Windows.Forms.Label();
      this.label3 = new System.Windows.Forms.Label();
      this.InInitialWait = new System.Windows.Forms.MaskedTextBox();
      this.InMultiplier = new System.Windows.Forms.MaskedTextBox();
      this.label2 = new System.Windows.Forms.Label();
      this.BtCancel = new System.Windows.Forms.Button();
      this.label4 = new System.Windows.Forms.Label();
      this.OutLongestConnection = new System.Windows.Forms.Label();
      this.SuspendLayout();
      // 
      // BtStart
      // 
      this.BtStart.Location = new System.Drawing.Point(13, 394);
      this.BtStart.Name = "BtStart";
      this.BtStart.Size = new System.Drawing.Size(75, 23);
      this.BtStart.TabIndex = 0;
      this.BtStart.Text = "Start";
      this.BtStart.UseVisualStyleBackColor = true;
      this.BtStart.Click += new System.EventHandler(this.BtStart_Click);
      // 
      // OutStatus
      // 
      this.OutStatus.Location = new System.Drawing.Point(13, 13);
      this.OutStatus.Multiline = true;
      this.OutStatus.Name = "OutStatus";
      this.OutStatus.ReadOnly = true;
      this.OutStatus.ScrollBars = System.Windows.Forms.ScrollBars.Both;
      this.OutStatus.Size = new System.Drawing.Size(766, 375);
      this.OutStatus.TabIndex = 1;
      // 
      // InConnections
      // 
      this.InConnections.Location = new System.Drawing.Point(180, 397);
      this.InConnections.Mask = "00";
      this.InConnections.Name = "InConnections";
      this.InConnections.Size = new System.Drawing.Size(22, 20);
      this.InConnections.TabIndex = 2;
      this.InConnections.Text = "10";
      this.InConnections.TextChanged += new System.EventHandler(this.InConnections_TextChanged);
      // 
      // label1
      // 
      this.label1.AutoSize = true;
      this.label1.Location = new System.Drawing.Point(108, 400);
      this.label1.Name = "label1";
      this.label1.Size = new System.Drawing.Size(66, 13);
      this.label1.TabIndex = 3;
      this.label1.Text = "Connections";
      // 
      // label3
      // 
      this.label3.AutoSize = true;
      this.label3.Location = new System.Drawing.Point(289, 399);
      this.label3.Name = "label3";
      this.label3.Size = new System.Drawing.Size(113, 13);
      this.label3.TabIndex = 5;
      this.label3.Text = "Initial Connection Wait";
      // 
      // InInitialWait
      // 
      this.InInitialWait.Location = new System.Drawing.Point(408, 396);
      this.InInitialWait.Mask = "00";
      this.InInitialWait.Name = "InInitialWait";
      this.InInitialWait.Size = new System.Drawing.Size(21, 20);
      this.InInitialWait.TabIndex = 4;
      this.InInitialWait.Text = "60";
      this.InInitialWait.TextChanged += new System.EventHandler(this.InConnections_TextChanged);
      // 
      // InMultiplier
      // 
      this.InMultiplier.Location = new System.Drawing.Point(262, 396);
      this.InMultiplier.Mask = "0";
      this.InMultiplier.Name = "InMultiplier";
      this.InMultiplier.Size = new System.Drawing.Size(21, 20);
      this.InMultiplier.TabIndex = 2;
      this.InMultiplier.Text = "2";
      this.InMultiplier.TextChanged += new System.EventHandler(this.InConnections_TextChanged);
      // 
      // label2
      // 
      this.label2.AutoSize = true;
      this.label2.Location = new System.Drawing.Point(208, 400);
      this.label2.Name = "label2";
      this.label2.Size = new System.Drawing.Size(48, 13);
      this.label2.TabIndex = 3;
      this.label2.Text = "Multiplier";
      // 
      // BtCancel
      // 
      this.BtCancel.Location = new System.Drawing.Point(13, 436);
      this.BtCancel.Name = "BtCancel";
      this.BtCancel.Size = new System.Drawing.Size(75, 23);
      this.BtCancel.TabIndex = 6;
      this.BtCancel.Text = "Cancel";
      this.BtCancel.UseVisualStyleBackColor = true;
      this.BtCancel.Click += new System.EventHandler(this.BtCancel_Click);
      // 
      // label4
      // 
      this.label4.AutoSize = true;
      this.label4.Location = new System.Drawing.Point(451, 399);
      this.label4.Name = "label4";
      this.label4.Size = new System.Drawing.Size(102, 13);
      this.label4.TabIndex = 7;
      this.label4.Text = "Longest Connection";
      // 
      // OutLongestConnection
      // 
      this.OutLongestConnection.AutoSize = true;
      this.OutLongestConnection.Location = new System.Drawing.Point(559, 399);
      this.OutLongestConnection.Name = "OutLongestConnection";
      this.OutLongestConnection.Size = new System.Drawing.Size(102, 13);
      this.OutLongestConnection.TabIndex = 8;
      this.OutLongestConnection.Text = "Longest Connection";
      // 
      // Form1
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(791, 582);
      this.Controls.Add(this.OutLongestConnection);
      this.Controls.Add(this.label4);
      this.Controls.Add(this.BtCancel);
      this.Controls.Add(this.label3);
      this.Controls.Add(this.InInitialWait);
      this.Controls.Add(this.label2);
      this.Controls.Add(this.InMultiplier);
      this.Controls.Add(this.label1);
      this.Controls.Add(this.InConnections);
      this.Controls.Add(this.OutStatus);
      this.Controls.Add(this.BtStart);
      this.Name = "Form1";
      this.Text = "Form1";
      this.Load += new System.EventHandler(this.Form1_Load);
      this.ResumeLayout(false);
      this.PerformLayout();

    

    #endregion

    private System.Windows.Forms.Button BtStart;
    private System.Windows.Forms.TextBox OutStatus;
    private System.Windows.Forms.MaskedTextBox InConnections;
    private System.Windows.Forms.Label label1;
    private System.Windows.Forms.Label label3;
    private System.Windows.Forms.MaskedTextBox InInitialWait;
    private System.Windows.Forms.MaskedTextBox InMultiplier;
    private System.Windows.Forms.Label label2;
    private System.Windows.Forms.Button BtCancel;
    private System.Windows.Forms.Label label4;
    private System.Windows.Forms.Label OutLongestConnection;
  

【讨论】:

感谢您分享您的代码。我尝试使用位于同一网络上的开发服务器并得到相同的错误,它是一个完全不同的网络、操作系统、Oracle 版本(11g)。生产oracle服务器非常稳定,我们以前从未遇到过任何问题,只有在使用托管库时。也用另一个系统测试过,使用休眠,同样的错误。它现在可以工作,但我不满意,我会按照你在这里的建议做更多的测试。谢谢! 我的开发机器上没有。在我测试过的所有环境中,生产服务器是唯一具有此文件的服务器。无论如何,我尝试了一些与 sqlnet.ora 相关的配置,以及 web.config 的“oracle.manageddataaccess.client”部分。【参考方案2】:

在禁用池 (Pooling=False) 后,正如 @bdn02 建议的那样,我可以确认它有效。但是我认为它应该会影响性能,并且我担心在没有任何池的情况下将此代码发布到生产中(我认为标准值是可以的)。

所以我尝试了许多配置,看起来不知何故(不是很清楚)oracle 的池管理引发了 ORA-12570 错误,一段时间后,会话关闭,应用程序再次运行。

为了找到启用池的最佳配置,我创建了一个测试应用程序来启动 50 个线程(每个线程每 50 毫秒执行 1 次测试),并减少默认池值直到错误停止。通过这种方式,我能够获得最佳配置,稳定,没有任何错误。

显然它并不适用于每个服务器,但这是我的最终连接字符串配置:

Pooling=true;Min Pool Size=1;Connection Lifetime=180;Max Pool Size=50;Incr Pool Size=5

【讨论】:

似乎是 ODP.NET 托管驱动程序中的一个错误(它仍然很新并且有一些错误)。我建议在 Oracle 支持处也开一张票。 是的,在禁用池的情况下,应用程序很慢。您可以检查的另一个选项是在连接字符串中添加“验证连接”属性 @WernfriedDomscheit 如果更改 Pooling 属性可以解决这个问题,我不会说这一定是 ODP .NET 驱动程序的错,而是数据库处理多线程的能力。除了 ODP 驱动程序建立的连接之外,其他连接也会引起数据库的注意,并且池应该处理它。如果不是,那是数据库端的缺陷,不一定是用于连接数据库的驱动程序,除非单个应用程序通过太快或一次推送太多线程(更高的池比 DB 可以处理的大小)。然后就是司机了。 @vpacguy 可以配置数据库处理多线程的能力,但不管它有多大,如果驱动器存在以完全错误的方式消耗池的错误,数据库将除了保护自己关闭进一步的连接之外别无选择。我做了这个测试,我将池的大小增加到默认值的两倍,结果是该错误出现的时间增加了大约 1 小时。顺便说一下,本机驱动程序在配置非常低的池限制时运行良好。所以,这是托管驱动程序的一个错误。 我会选择 min pool size = 0 而不是 1。一夜之间留下的一个连接仍然可能被终止,然后它在早上就死了。【参考方案3】:

我给你一个我用来检查数据库连接的 powershell 脚本。 $baselogpath = "" $filesuffix = "_GetDBConnection" $dbuser ="" $dbpassword ="" $dbalias = ""; $command = new-Object Oracle.DataAccess.Client.OracleCommand($queryString, $connection); $connection.Open(); $count = $command.ExecuteScalar(); $connection.Close(); $message = "Records found: " + $count; $esito = "OK"; Catch $message = $_.Exception.Message; $esito = "KO"; $now = Get-Date $filename = $baselogpath + $now.Year + $now.Month.Tostring("00") + $now.Day.Tostring("00") + $filesuffix + ".log" if (!(Test-Path($filename))) $fileheader = "Time Esito, Elapsed, Message" $fileheader > $filename $Time.Stop(); $Elapsed = $Time.Elapsed; $row = $now.Hour.toString("00") + ":" + $now.Minute.toString("00") + ":" + $now.Second.toString("00") + " " + $esito + "," + $Elapsed.Hours.toString("00") + ":" + $Elapsed.Minutes.toString("00") + ":" + $Elapsed.Seconds.toString("00") + "," + $message; $row >> $filename

您能否尝试使用 Oracle 托管 dll 的托管版本每分钟安排一次此脚本? 我会理解问题是否仅出在 Web 应用程序上,或者是否与 Oracle 托管驱动程序有关。 如果您要进行高级测试,您可以安排使用非托管版本的 oracle.dataaccess 的此脚本的副本。

祝你好运

【讨论】:

我做了一个类似的测试,但使用的是一个 windows 窗体应用程序,没有计划,但得到了与 web 应用程序相同的错误。我将像您的脚本一样对循环和记录测试进行一些更改。但是.... Pooling=False 到目前为止没有错误...我将在等待时安排此测试。谢谢!【参考方案4】:

我在使用带有 ODAC 12c 第 4 版的 SQL Server Reporting Services 2016 时遇到了同样的间歇性错误:

Error:
An error has occurred during report processing. (rsProcessingAborted) 
Query execution failed for dataset 'TermPrompt'. (rsErrorExecutingCommand) 
ORA-12570: Network Session: Unexpected packet read error 
ORA-12570: Network Session: Unexpected packet read error 
ORA-12537: Network Session: End of file

在s-s-rS的Oracle数据源中加入pooling参数Data Source="myOracleDB";Pooling="false"彻底解决了这个问题。

立即重新执行报告工作正常。

我意识到每次创建新连接而不是使用池时都会出现潜在的性能问题,但在 Oracle 修复此问题之前,我不希望我的用户遇到此错误。

【讨论】:

与在其他答案/cmets 上观察到的完全一样。我们有一个 30% 的性能下降禁用池,所以,就我而言,这是不可接受的,我将其替换为非托管版本。【参考方案5】:

我在应用程序异常中收到此错误。内部异常中没有更多有用的细节。更改池选项并不能解决问题,禁用池也没有。启用跟踪后,它会在跟踪文件中显示不同的错误“ORA-12537 network session end of file”(未传播到应用程序异常)。该线程表明旧版本的 oracle 驱动程序是罪魁祸首。我查了一下,我使用的是 2014 年的版本。升级到 2017/12.2c/12.2.0.1.0 版本解决了这个问题。

【讨论】:

【参考方案6】:

KeepAlive 设置,可以防止丢失连接的池错误,例如 ORA-12571 和类似的。 (而不是禁用池)

问题及解决方案: https://github.com/oracle/dotnet-db-samples/issues/58

在打开连接之前设置connection.KeepAlive = true;。您还需要具有不低于 2.19.100 的 Oracle.ManagedDataAccess.Core 版本(不了解非核心应用程序)。

我在生产版本“Oracle 错误 ORA-12571 现有连接被远程主机强行关闭”和“ORA-03135:连接失去联系”与 .Net Core 3.0 和设置帮助时遇到了难以理解的偶发池错误。

【讨论】:

以上是关于ODP.NET Oracle.ManagedDataAcess 随机 ORA-12570 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ODP.Net 传递字节数组?

.NET Core 使用ODP.NET Core连接操作Oracle数据库

ODP.Net 中的连接字符串

ODP.NET TNS:无法解决错误

将 System.Data.OracleClient 替换为 Oracle.DataAccess (ODP.NET)

将 ODP.Net 与 NHibernate 与 .net System.decimal 一起使用