ODP.net managed driver throws ORA-12570: Network S

2019-03-11 05:25发布

问题:

In one of our products we retrieve data from the Oracle database using stored procedures using the ODP.net managed driver.

Every now and then (roughly every 1000 queries) we get the following exception:

(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()

It seems like ODP.net is calling System.Net.Sockets.Socket.Receive with an invalid size parameter (<=0 or greater than the length of buffer minus the value of the offset parameter).

The exception cannot be reproduced manually and is never raised while executing different procedures with different parameters (ie it's random).

Configuration: ODP.net managed driver version: 4.121.1.0 .net framework 4.5 Oracle server version: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 (Linux)

Has anyone already experienced this issue? Are there any fixes available?

Thanks in advance!

回答1:

After opening a ticket with the Oracle support, they sent an unofficial updated version of the managed ODP.net library which seems to fix the issue.

Hopefully the fix should be part of the next ODAC release (the latest available today is from Oct 2015).

If you see this error in your application, it's probably due to the same bug in the managed ODP.net library, not the way you use it.



回答2:

After reading through a similar question at ODP.NET Oracle.ManagedDataAcess random ORA-12570 errors, it seems like it's actually a pooling problem. Apparently the answer is to either set Pooling=false in the Connection String, or to find out just how many threads can be opened and how long the connection can be open before it becomes too much for Oracle to handle. This was the answer the author of that question posted:

To find the best configuration with pooling enabled I created a test application to start 50 threads (each one doing 1 test each 50ms), and decreased the default pool values until the error stoped. This way I was able to get an optimal configuration, stable, without any errors.

Obviously it does not applies to every server, but this is my final connection string configuration:

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