Dans l'un de nos produits, nous récupérons les données de la base de données Oracle à l'aide de procédures stockées à l'aide du pilote géré ODP.net.
De temps en temps (environ toutes les 1000 requêtes), nous obtenons l'exception suivante:
(ORA-12570: Network Session: Unexpected packet read error)
---> Oracle.ManagedDataAccess.Client.OracleException: ORA-12570: Network Session: Unexpected packet read error
---> OracleInternal.Network.NetworkException: ORA-12570: Network Session: Unexpected packet read error
---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: size
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError& errorCode)
at OracleInternal.Network.ReaderStream.ReadIt(OraBuf OB, Int32 len)
--- End of inner exception stack trace ---
at OracleInternal.Network.ReaderStream.ReadIt(OraBuf OB, Int32 len)
at OracleInternal.Network.ReaderStream.WaitForReset()
at OracleInternal.Network.OracleCommunication.Reset()
at OracleInternal.TTC.TTCExecuteSql.ReceiveExecuteResponse(Accessor[]& defineAccessors, Accessor[] bindAccessors, Boolean bHasReturningParams, SQLMetaData& sqlMetaData, SqlStatementType statementType, Int64 noOfRowsFetchedLastTime, Int32 noOfRowsToFetch, Int32& noOfRowsFetched, Int64& queryId, Int32 longFetchSize, Int32 initialLOBFetchSize, Int64[] scnFromExecution, Boolean& bAllPureInputBinds, DataUnmarshaller& dataUnmarshaller, MarshalBindParameterValueHelper& marshalBindParamsHelper, Boolean bDefineDone, Boolean& bMoreThanOneRowAffectedByDmlWithRetClause)
--- End of inner exception stack trace ---
at Oracle.ManagedDataAccess.Client.OracleException.HandleError(OracleTraceLevel level, OracleTraceTag tag, Exception ex)
at OracleInternal.TTC.TTCExecuteSql.ReceiveExecuteResponse(Accessor[]& defineAccessors, Accessor[] bindAccessors, Boolean bHasReturningParams, SQLMetaData& sqlMetaData, SqlStatementType statementType, Int64 noOfRowsFetchedLastTime, Int32 noOfRowsToFetch, Int32& noOfRowsFetched, Int64& queryId, Int32 longFetchSize, Int32 initialLOBFetchSize, Int64[] scnFromExecution, Boolean& bAllPureInputBinds, DataUnmarshaller& dataUnmarshaller, MarshalBindParameterValueHelper& marshalBindParamsHelper, Boolean bDefineDone, Boolean& bMoreThanOneRowAffectedByDmlWithRetClause)
at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteNonQuery(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, Int32 longFetchSize, Int32 lobPrefetchSize, OracleDependencyImpl orclDependencyImpl, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Boolean isFromEF)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery()
Il semble que ODP.net appelle System.Net.Sockets.Socket.Receive avec un paramètre de taille non valide (<= 0 ou supérieur à la longueur de la mémoire tampon moins la valeur du paramètre offset).
L'exception ne peut pas être reproduite manuellement et n'est jamais déclenchée lors de l'exécution de procédures différentes avec des paramètres différents (c'est-à-dire aléatoires).
Configuration: Version du pilote géré ODP.net: 4.121.1.0 . Net framework 4.5 Version du serveur Oracle: Oracle Database 11g édition Enterprise Edition 11.2.0.4.0 (Linux)
Quelqu'un at-il déjà rencontré ce problème? Existe-t-il des correctifs disponibles?
Merci d'avance!
Après avoir ouvert un ticket avec le support Oracle, ils ont envoyé une version mise à jour non officielle de la bibliothèque gérée ODP.net, qui semble résoudre le problème.
Espérons que le correctif devrait faire partie de la prochaine version d'ODAC (la dernière disponible aujourd'hui date d'octobre 2015).
Si vous voyez cette erreur dans votre application, c'est probablement à cause du même bogue dans la bibliothèque gérée ODP.net, et non de la manière dont vous l'utilisez.
Après avoir lu une question similaire sur ODP.NET Oracle.ManagedDataAcess erreurs aléatoires ORA-12570 , il semble que ce soit en fait un problème de mise en commun. Apparemment, la solution consiste soit à définir Pooling=false
dans la chaîne de connexion, soit à déterminer le nombre de threads pouvant être ouverts et la durée pendant laquelle la connexion peut être ouverte avant qu'elle ne devienne trop difficile à gérer pour Oracle. C'est la réponse que l'auteur de cette question a postée:
Pour trouver la meilleure configuration avec la mise en pool activée, j'ai créé une application de test permettant de démarrer 50 threads (chacun effectuant 1 test toutes les 50 ms) et diminué les valeurs de pool par défaut jusqu'à la résolution de l'erreur. De cette façon, j'ai pu obtenir une configuration optimale, stable, sans erreur.
Évidemment, cela ne s'applique pas à tous les serveurs, mais voici la configuration finale de ma chaîne de connexion:
Pooling=true;Min Pool Size=1;Connection Lifetime=180;Max Pool Size=50;Incr Pool Size=5