簡體   English   中英

OracleConnection 連接請求超時

[英]OracleConnection Connection Request Timed out

在 a.Net Core 3.1 多線程控制台應用程序中出現問題; 如果對ThreadPool.QueueUserWorkItem的調用次數超過ThreadPool.SetMaxThreads中設置的線程數, OracleConnection將始終拋出“連接請求超時”異常。 “任務”是對 Oracle 中存儲過程的調用,該過程通過 cursor 返回數據。 在一個線程中一切正常,沒有問題

這是 in.Net Core 3.1 使用 Oracle.ManagedDataAccess.Client 的最新 nuget 版本

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

一些線程留在以下 state “搜索空閑連接”:

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 information\t", taskName) +
                      String.Format("   Thr ID: {0}\t\t", thread.ManagedThreadId);
            }

            Console.WriteLine(msg);
        }
    }
}

我遇到過同樣的問題。 使用線程而不是任務修復了它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM