OracleConnection连接请求超时



在中出现问题。Net Core 3.1多线程控制台应用程序OracleConnection将一致地为";连接请求超时";如果调用ThreadPool的次数。QueueUserWorkItem超过了在线程池中设置的线程数。设置最大线程数。";任务";是对Oracle中存储过程的调用,该过程通过游标返回数据。在单个线程中,所有工作都很好,没有问题

这是在。Net Core 3.1使用Oracle的最新nuget版本。ManagedDataAccess。客户端

已经尝试了Oracle连接字符串、池大小、连接生存期连接超时等设置的许多组合。似乎没有任何帮助。一旦排队的任务数超过线程数,连接上的Open调用将引发异常。

使用OracleConfiguration进行跟踪揭示了一个异常:

2020-09-23 21:30:51.997780 TID:6   (PRI) (ERR) (CP) PoolManager.CreateNewPR() (txnid=n/a) Oracle.ManagedDataAccess.Client.OracleException (0x80004005): Connection request timed out
at OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, OracleConnection connRefForCriteria, String instanceName, List`1 switchFailedInstNames)

一些线程处于以下状态";搜索空闲连接":

2020-09-23 21:28:57.443815 TID:13  (PRI) (ENT) (CP) PoolManager.Get() MultiTenant : Searching for a idle connection, retryCountWithoutAffinity: 0

要复制的代码:

using Oracle.ManagedDataAccess.Client;
using Oracle.ManagedDataAccess.Types;
using System;
using System.Data;
using System.Diagnostics;
using System.Threading;
namespace OracleDBStoredProc
{
class Program
{
private static Object lockObj = new Object();
static void Main(string[] args)
{
int numThreads = 10;
ThreadPool.SetMaxThreads(numThreads, numThreads);
for (int i = 0; i < numThreads+ 1; i++)
{
string myMsg = $" TASK {i} ";
ThreadPool.QueueUserWorkItem(CallToDatabase, myMsg);
Console.WriteLine(myMsg + " created.");
}
Console.WriteLine("Finished");
Console.ReadKey();
}
static void CallToDatabase(Object stateInfo)
{
OracleConfiguration.TraceOption = 1;
OracleConfiguration.TraceFileLocation = @"C:traces";
OracleConfiguration.TraceLevel = 2;
string taskName = (string)stateInfo;
Console.WriteLine(taskName + "started");
string constr = "User Id=MyUser;Password=MyPswd;Data Source=(DESCRIPTION= (ADDRESS= (PROTOCOL=tcp)(HOST=MyServer)(PORT=1521))(CONNECT_DATA= (SERVICE_NAME=myservice)))";
OracleConnection con = new OracleConnection(constr);
con.Open();
var cmd = new OracleCommand("MY_APP.GET_MY_DATA", con)
{
CommandType = CommandType.StoredProcedure
};
OracleParameter p1 = cmd.Parameters.Add("refcur_ret", OracleDbType.RefCursor, ParameterDirection.Output);
p1.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
OracleDataReader reader1 = ((OracleRefCursor)p1.Value).GetDataReader();
DataTable test = new DataTable();
test.Load(reader1);
reader1.Close();
reader1.Dispose();
p1.Dispose();
cmd.Dispose();
con.Close();
con.Dispose();
String msg = null;
Thread thread = Thread.CurrentThread;
lock (lockObj)
{
msg = String.Format("{0} thread informationt", taskName) +
String.Format("   Thr ID: {0}tt", thread.ManagedThreadId);
}
Console.WriteLine(msg);
}
}
}

我遇到了同样的问题。使用线程而不是任务可能会有所帮助。

更新:经过仔细调查,我发现当您使用大量任务时,Oracle驱动程序排队的ThreadPool工作线程启动速度会变慢,最终会导致(假(连接超时。

有几个解决方案:

解决方案1:增加线程池的最小线程数,例如:

ThreadPool.SetMinThreads(50, 50);  // YMMV

解决方案2:将连接配置为使用池,并适当设置其最小大小。

var ocsb = new OracleConnectionStringBuilder();
ocsb.DataSource = ocsb.DataSource;
ocsb.UserID = "myuser";
ocsb.Password = "secret";
ocsb.Pooling = true;
ocsb.MinPoolSize = 20; // YMMV

重要提示:在调用任何创建大量任务的例程之前,请使用"打开单个连接;"预热";池:

using(var oc = new OracleConnection(ocsb.ToString()))
{
oc.Open();
oc.Close();
}

注意:Oracle通过连接字符串(删除密码(对连接池进行索引,因此,如果要打开其他连接,则必须始终使用完全相同的连接字符串。

相关内容

  • 没有找到相关文章

最新更新