ODP.NET Oracle.ManagedDataAcess erreurs aléatoires ORA-12570
j'essaie de migrer vers Oracle.ManagedDataAcess du non géré version et recevoir des randoms ORA-12570 TNS:paquet de lecteur de l'échec.
Je ne sais pas pourquoi cette erreur commence, mais une fois qu'elle commence, chaque requête subséquente donne la même erreur pendant environ 10-30 minutes, puis elle fonctionne à nouveau pendant 10-30 minutes et ainsi de suite.
il s'agit donc d'un aléatoire d'échecs subséquents pendant un certain temps, puis de succès subséquents
Déjà essayé beaucoup de choses, à cv:
L'environnement:
- Oracle.ManagedDataAcess version 12.1.2400 (4.121.2.20150926) (nuget) (pas de gac de référence installé sur le serveur qui pourrait remplacer le bac version)
- Oracle Serveur de Base de données Oracle 12c Enterprise Edition Version 12.1.0.2.0 - 64bit de la Production
- Windows 2012 (mise à Jour de Windows ok)
Vérifié:
- Pare-feu: Il n'est pas un pare-feu de problème
- Erreur Machine: le même problème se produit sur ma machine, Azure WebApp et une Instance AWS EC2
- interférences: il n'y a pas d'exécution de sniffer, de proxy transparent, etc.
- de Cryptage: je n'ai pas utiliser n'importe quel type de cryptage (sauf si il y a quelque chose activé par défaut je ne sais pas)
- connections string: la même chaîne de connexion fonctionne parfaitement avec la version non gérée
Suplementaire informations:
- il s'agit D'une base de données de production, elle est très stable
- l'application est compilée à anycpu, le pool d'applications IIS est limité à 64bits
- Im test exactement la même demande à chaque fois (juste un rafraîchissement sur une url d'un repos ws, webapi), de sorte qu'il n'est pas lié au format de données
Configuration:
le Serveur sqlnet.ora
SQLNET.AUTHENTICATION_SERVICES= (NTS) NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
Application 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>
Quelques références:
https://community.oracle.com/thread/3634263?start=0&tstart=0
ODP.net le pilote géré lance ORA-12570: session réseau: erreur inattendue de lecture de paquet
a géré Oracle Client avec Oracle Advanced Security Options
ODP.NET erreur dans IIS: ORA-12357 Réseau de la Fin de la Session de fichier
UPDATE 1
après le changement de pooling (comme je l'ai décrit comme une réponse ici), j'ai décidé de publier une version pour faire de vrais tests. Après 1 jour et les utilisateurs se plaignant de la performance j'ai eu une autre erreur: la valeur ne peut pas être nulle. Nom du paramètre: byteArray
j'ai changé la référence de nouveau à la version non gérée et tout allait bien à nouveau, plus vite, sans erreur de bytearray, mieux mutualisation de la gestion.
donc je laisse tomber la version managée pour l'instant, peut-être que je vais essayer à nouveau sur Oracle la prochaine version.
voici quelques références sur cette nouvelle erreur, comme vous pouvez le voir, ressemble à un autre bug (toujours sans réponse).
https://community.oracle.com/thread/3676588?start=0&tstart=0
EF + ODP.NET + CLOB = la valeur ne peut pas être nulle-nom du paramètre: byteArray?
jusqu'à présent, raisons d' ne pas utiliser:
- mise en commun de la gestion bogue
- CLOB null / not null bytearray errors
- dégradation des performances probablement liée à la mise en commun des bogues
5 réponses
après avoir désactivé le pooling (Pooling=False), comme @bdn02 l'a suggéré, je pourrais confirmer que cela a fonctionné. Cependant, je pense que cela devrait affecter la performance et je me suis inquiété de publier ce code dans la production sans aucune mise en commun (je pensais que les valeurs standard étaient ok).
J'ai donc essayé de nombreuses configurations et j'ai l'impression (ce n'est pas très clair) que la gestion de la piscine d'oracle soulevait une erreur ORA-12570 et, après un certain temps, les sessions sont fermées et les l'application fonctionne à nouveau.
pour trouver la meilleure configuration avec pooling activé j'ai créé une application de test pour lancer 50 threads (chacun faisant 1 test chaque 50ms), et j'ai diminué les valeurs par défaut de pool jusqu'à ce que l'erreur s'arrête. De cette façon, j'ai pu obtenir une configuration optimale, stable, sans aucune erreur.
évidemment, cela ne s'applique pas à tous les serveurs, mais c'est ma dernière configuration de chaîne de connexion:
Pooling=true;Min Pool Size=1;Connection Lifetime=180;Max Pool Size=50;Incr Pool Size=5
D'après mon expérience avec une erreur similaire 12570 (lecteur vs écrivain) il n'y a qu'une seule raison à cette erreur - quelque chose sur votre réseau est la fin des connexions TCP inactives. C'est généralement un pare-feu/commutateur géré. Vous avez dit que vous aviez déjà exclu le pare-feu, mais je ne sais pas comment. Il est possible que le db lui-même termine les connexions (script dba), mais je me souviens que c'était une erreur différente.
Ora-12571 pourrait être légèrement différent. Mais encore depuis que vous avez identifié que le problème est le même en ce que c'est des connexions de piscine établies de longue date que je vais continuer.
- définir min pool size = 0 dans la chaîne de connexion. En général, ça répare les choses pour moi. Il permet à l'ensemble de la piscine pour être fermée lorsque l'application est inactive. Il y a une petite chance cependant que si votre trafic oscille violemment, la taille de la piscine decr pourrait avoir besoin d'être augmentée afin de fermer plus rapidement les connexions créé par une course folle.
- définir Expire_Time dans sqlnet.ora. Pas évident par son nom, ce paramètre envoie un paquet prob, ce qui permet de satisfaire n'importe quel contrôle de ralenti tcp. Le seul problème ici est que je ne suis pas tout à fait sûr de la façon de définir les paramètres de sqlnet avec le fournisseur géré. Je devine que sqlnet.ora peut aller dans l'exe dir mais je vois aussi une indication qu'il peut être mis dans la .config sous la forme de (voir un exemple similaire de wallet_override ici) Parce que vous obtenez seulement cela dans le fournisseur géré, je me demande si votre client non géré sqlnet.ora a déjà ce paramètre.
j'ai vu cela de nombreuses fois au cours des années et la première fois que c'est arrivé j'ai créé un utilitaire qui fait essentiellement une recherche binaire pour déterminer le temps d'arrêt exact en créant des connexions de durées variables. S'il atterrit toujours à la même heure de terminaison, vous pouvez deviner qu'il y a un contexte quelque part qui cause ça. Si c'est erratique, alors vous avez peut-être un problème d'infrastructure.
malheureusement, je l'ai créé comme une application c # forms, donc j'ai collé à la fois le code de la forme et le code designer ci-dessous:
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;
}
}
je vous donne un script powershell que j'utilise pour vérifier la connectivité de base de données.
$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
pouvez-vous essayer de programmer ce script toutes les minutes, en utilisant la version gérée de la dll gérée par Oracle? Je comprendrais si le problème est seulement sur l'application web ou si est Oracle managed driver lié. Vous voulez faire un test avancé, vous pouvez programmer une copie de ce script qui utilise la version non gérée d'oracle.dataaccess.
Bonne chance
j'ai rencontré cette même erreur intermittente en utilisant SQL Server Reporting Services 2016 avec ODAC 12c version 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
ajout du paramètre pooling Data Source="myOracleDB";Pooling="false"
à la source de données Oracle dans SSRS complètement résolu le problème.
une ré-exécution immédiate du rapport fonctionne très bien.
je me rends compte qu'il y a des problèmes de performance potentiels dans la création d'une nouvelle connexion à chaque fois plutôt que d'utiliser la piscine, mais jusqu'à ce Qu'Oracle corrige cela, je ne veux pas de utilisateurs rencontrant cette erreur.
je recevais cette erreur dans une exception d'application. Il n'y avait pas plus de détails utiles dans l'exception interne. La modification des options de mise en commun n'a pas réglé le problème, pas plus que la désactivation de la mise en commun. Une fois le traçage est activé, c'était une erreur " ORA-12537 session réseau fin du fichier " dans le fichier de trace (non propagé à l'exception de la demande). Ce fil suggère qu'une ancienne version du pilote oracle est à blâmer. J'ai vérifié, et j'utilisais la version de 2014. Mise à niveau vers le 2017/12.2 C / 12.2.0.1.0 version a résolu le problème.