ODP.NET Oracle.ManagedDataAcess случайные ошибки ORA-12570

Я пытаюсь перейти на Oracle.ManagedDataAcess с неуправляемой версии и получать случайные ошибки. ORA-12570 TNS: сбой программы чтения пакетов.

Я не знаю, почему возникает эта ошибка, но как только она запускается, каждый последующий запрос выдает такую ​​же ошибку в течение 10-30 минут, затем снова работает в течение еще 10-30 минут и так далее.

Таким образом, это случайные последующие неудачи в течение некоторого времени, а затем последующего успеха

Уже много чего перепробовал, чтобы возобновить

Окружающая среда:

  • Oracle.ManagedDataAcess версия 12.1.2400 (4.121.2.20150926) (nuget) (на сервере не установлена ​​ссылка gac, которая могла бы переопределить версию bin)
  • Oracle Server Oracle Database 12c Enterprise Edition, выпуск 12.1.0.2.0 - 64-разрядная версия
  • Windows 2012 (Windows Update в порядке)

Проверено:

  • Брандмауэр: это не проблема брандмауэра
  • Ошибка компьютера: та же проблема возникает на моем компьютере, Azure WebApp и экземпляре AWS EC2
  • Интерференция: нет запущенного анализатора, прозрачного прокси и т. Д.
  • Шифрование: я не использую какой-либо вид шифрования (если по умолчанию не включено что-то, чего я не знаю)
  • Строка соединений: та же строка соединений отлично работает с неуправляемой версией

Дополнительная информация:

  • Это производственная база данных, она очень стабильная
  • Приложение скомпилировано в anycpu, пул приложений IIS ограничен до 64 бит
  • Я тестирую точно один и тот же запрос каждый раз (просто обновление по get url rest ws, webapi), поэтому он не связан с форматом данных

Конфигурация:

Сервер 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 выбрасывает ORA-12570: сетевой сеанс: непредвиденная ошибка чтения пакета

Управляемый клиент Oracle с опциями расширенной безопасности Oracle

Ошибка ODP.NET в IIS: конец сеанса сетевого сеанса ORA-12357

ОБНОВЛЕНИЕ 1

После того, как пул изменился (как я здесь описал как ответ), я решил опубликовать версию, чтобы провести настоящий тест. Через 1 день, когда пользователи жалуются на производительность, я получил еще одну ошибку: значение не может быть нулевым. Имя параметра: byteArray

Я вернул ссылку на неуправляемую версию, и все снова было в порядке, быстрее, без ошибок байтового массива, улучшено управление пулом.

Так что сейчас я просто отказываюсь от управляемой версии, может быть, я попробую еще раз на Oracle в следующем выпуске.

Здесь некоторые ссылки на эту новую ошибку, как вы можете видеть, выглядят как еще одна ошибка (до сих пор без ответа).

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

EF + ODP.NET + CLOB = Значение не может быть пустым - Имя параметра: byteArray?

Пока что причины не использовать:

  • Ошибка управления пулами
  • CLOB ошибки null/not null bytearray
  • Снижение производительности, вероятно, связано с ошибкой объединения

7 ответов

По моему опыту с подобной ошибкой 12570 (читатель против писателя) есть только одна причина этой ошибки - что-то в вашей сети прерывает неактивные tcp-соединения. Обычно это межсетевой экран / управляемый коммутатор. Вы сказали, что уже исключили брандмауэр, но я не знаю как. Возможно, что сама база данных прерывает соединения (скрипт dba), но я вспоминаю, что это другая ошибка.

Ora-12571 может немного отличаться. Но все же, так как вы определили, что проблема та же в том, что это давно установленные подключения к пулу, я продолжу.

Есть пара вещей, которые вы можете сделать:

  1. Установите минимальный размер пула = 0 в строке подключения. Это обычно исправляет вещи для меня. Это позволяет закрывать весь пул, когда приложение бездействует. Однако существует небольшая вероятность того, что, если ваш трафик сильно колеблется, возможно, потребуется увеличить размер пула decr, чтобы быстрее закрывать соединения, созданные в результате безумного рывка.
  2. Установите Expire_Time в sqlnet.ora. Неочевидно по названию, этот параметр отправляет пробный пакет, что приводит к выполнению любого мониторинга простоя TCP. Единственная проблема здесь в том, что я не совсем уверен, как установить параметры sqlnet с управляемым провайдером. Я предполагаю, что sqlnet.ora может идти в exe dir, но я также вижу некоторые признаки того, что он может быть установлен в.config в форме (см. Аналогичный пример wallet_override здесь), потому что вы получаете только это в управляемом провайдере мне интересно, есть ли у этого неуправляемого клиента sqlnet.ora этот параметр.

Я видел это много раз за эти годы, и в первый раз, когда это произошло, я создал утилиту, которая в основном выполняет бинарный поиск, чтобы определить точное время ожидания путем создания соединений различной продолжительности. Если он постоянно попадает в одно и то же время завершения, вы можете догадаться, что где-то есть настройка, которая вызывает это. Если это ошибочно, то у вас может быть какая-то инфраструктурная слабость.

К сожалению, я создал его как приложение aC# forms, поэтому я вставил код формы и код конструктора ниже:

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}, max{1}, resolution{2}.", 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\n{2}",(IdleTime).ToString(), ex, ConnectionId);

          }
        }
        catch (Exception ex)
        {
          Notify("Unknown error occured on connection with timeout {0}, Error: {1}, \r\n{2}", (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;
  }
}

После отключения пула (Pooling=False), как подсказал @bdn02, я смог подтвердить, что он работает. Однако я думаю, что это должно повлиять на производительность, и я был обеспокоен публикацией этого кода в производство без какого-либо объединения (я думал, что стандартные значения были в порядке).

Поэтому я перепробовал множество конфигураций и, похоже, как-то (это не очень понятно) управление пулом oracle вызывало ошибку ORA-12570, и через некоторое время сессии закрывались, и приложение снова работало.

Чтобы найти наилучшую конфигурацию с включенным пулом, я создал тестовое приложение для запуска 50 потоков (каждый из которых выполняет 1 тест каждые 50 мс) и уменьшал значения пула по умолчанию, пока ошибка не прекратилась. Таким образом, я смог получить оптимальную конфигурацию, стабильную, без каких-либо ошибок.

Очевидно, что это не относится к каждому серверу, но это моя последняя конфигурация строки подключения:

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

Я случайно получаю эту ошибку в течение многих лет, потому что мое соединение теряется во многих отношениях.

Я решил эту проблему, используя подход повторной попытки :

      public string GetData(int retry = 3)
{
    string prop = string.Empty;
    try
    {
        var connectionString = "...";
        using (var conn = new OracleConnection(connectionString))
        {
            string sql = "SELECT NAME FROM USERS WHERE ID = 10";

            conn.Open();
            var cmd = new OracleCommand();
            cmd.Connection = conn;
            cmd.CommandText = sql;
            cmd.CommandType = CommandType.Text;
            var dr = cmd.ExecuteReader();

            if (dr.Read())
            {
                prop = dr["NAME"].ToString();
            }
        }

        return prop;
    }
    catch (OracleException ex)
    {
        //Retry on lost connection errors
        //In tests conducted, the following errors tend to occur when the connection is interrupted between the Open method and the ExecuteReader.
        if (ex.Number == 12570 || ex.Number == 03135 || ex.Number == 12571)
        {
            if (retry == 0)
                throw;

            return GetData(retry - 1);
        }

        throw;
    }
}

С помощью приведенного выше примера подхода вы можете делать такие вещи, как:

-Создайте методы расширения для использования, такие как ExecuteReaderWithRetry() и ExecuteNonQueryWithRetry(), и используйте их вместо исходных методов.

-Создайте класс, чтобы инкапсулировать эту логику и вызвать его вместо классов Oracle.

Если вы используете Entity Framework , вы можете настроить стратегию выполнения для повторной попытки при возникновении ошибок (12571, 12570, 03135 и т. д.).

Вот пример в Entity Framework Core:

      public class RetryOnErrorStrategy : OracleRetryingExecutionStrategy
{
    private static readonly IList<int> ErrorNumbersToRetry = new List<int>()
    {
        12570, 12571, 03135 //lost connection errors
    };

    public SomeRetryStrategy(ExecutionStrategyDependencies dependencies)
        : base(dependencies, DefaultMaxRetryCount, DefaultMaxDelay, ErrorNumbersToRetry)
    {
    }
}

public class YourDbContext : DbContext
{
    public YourDbContext(string connectionString)
       : base(OracleDbContextOptionsExtensions.UseOracle(new DbContextOptionsBuilder(), connectionString, oracleOptions =>
       {
           oracleOptions.ExecutionStrategy(dependencies =>
               new RetryOnErrorStrategy(
               dependencies));
       }).Options)
    {

    }

    public DbSet<SomeEntity> SomeEntity { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       ....
    }
    
    ....
}

См.
Ответ об экстратегии выполнения
ORA 12570 в Azure.

Я даю вам сценарий 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? Я бы понял, если проблема только в веб-приложении или если драйвер, связанный с Oracle. Если вы хотите сделать расширенный тест, вы можете запланировать копию этого сценария, который использует неуправляемую версию oracle.dataaccess.

Удачи

Я столкнулся с той же периодически возникающей ошибкой при использовании SQL Server Reporting Services 2016 с ODAC 12c Release 4:

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

Добавление параметра пула Data Source="myOracleDB";Pooling="false" к источнику данных Oracle в SSRS полностью решена проблема.

Немедленное повторное выполнение отчета работает нормально.

Я понимаю, что существуют потенциальные проблемы с производительностью при создании нового соединения каждый раз, а не при использовании пула, но пока Oracle не исправит это, я не хочу, чтобы мои пользователи сталкивались с этой ошибкой.

Существует настройка KeepAlive , которая может предотвратить ошибки пула потери соединения, такие как ORA-12571 и подобные. (вместо отключения объединения)

Проблема и решение:https://github.com/oracle/dotnet-db-samples/issues/58 .

Установлен connection.KeepAlive = true;перед открытием соединения. Вам также необходимо иметь версию Oracle.ManagedDataAccess.Core не ниже 2.19.100 (не знаю о не-Core приложениях).

У меня были непонятные случайные ошибки объединения в производственной версии «Ошибка Oracle ORA-12571 Существующее соединение было принудительно закрыто удаленным хостом» и «ORA-03135: связь потеряна» с .Net Core 3.0, и настройки помогли.

Я получаю эту ошибку в исключении приложения. Во внутреннем исключении больше не было полезных подробностей. Изменение параметров пула не устранило проблему и не отключило пул. После того, как трассировка была включена, в файле трассировки появилась другая ошибка " конец файла сетевого сеанса ORA-12537 " (не распространяется на исключение приложения). Этот поток предполагает, что виновата старая версия драйвера оракула. Я проверил и использовал версию от 2014 года. Обновление до версии 2017/12.2c/12.2.0.1.0 решило проблему.

Другие вопросы по тегам