Подтвердить что ты не робот

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 Release 12.1.0.2.0 - 64bit Production
  • Windows 2012 (Windows Update ok)

Проверено:

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

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

  • Это производственная база данных, она очень стабильна.
  • Приложение скомпилировано для anycpu, пул приложений IIS ограничен 64 битами
  • Я тестирую точно такой же запрос каждый раз (просто обновление на URL-адресе get 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

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

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

К сожалению, я создал его как приложение С# 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;
  }
}

Ответ 2

После отключения пула (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

Ответ 3

Я даю вам powershell script, который я использую для проверки подключения к базе данных. $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

Можно ли планировать эту script каждую минуту, используя управляемую версию управляемой dll Oracle? Я бы понял, если проблема связана только с веб-приложением или связана с управляемым драйвером oracle. Вы должны сделать расширенный тест, вы можете запланировать копию этого script, который использует неуправляемую версию oracle.dataaccess.

Удачи.

Ответ 4

Я столкнулся с такой же прерывистой ошибкой, используя 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 не исправляет это, я не хочу, чтобы мои пользователи столкнулись с этой ошибкой.