Мое понимание пула соединений; если строка соединения точно такая же, то мы повторно используем соединение вместо создания нового соединения.Пул соединений - один процесс - много потоков
Моя проблема в том, что я создаю много потоков для параллельной обработки. В этой «фиктивной» программе я создаю 500 потоков и позволяю функции ThreadPool обрабатывать потоки.
Шаги:
Каждая нить сделать таблицу обновления в SQL. (Указание метки времени для обновления)
Затем поток спит от 1 до 10 секунд (случайный).
В конце нить делает еще одно обновление в SQL (с указанием метки времени для конечного времени)
Затем нить выхода
class Program { static void Main(string[] args) { int numberOfThreads = 150; ThreadPool.SetMinThreads(numberOfThreads, numberOfThreads); ThreadPool.SetMaxThreads(numberOfThreads, numberOfThreads); List<Int64> chunkList = new List<Int64>(); int maxNumberOfChunks = 500; for (int i = 1; i < maxNumberOfChunks; i++) { chunkList.Add(i); } foreach (Int64 chunk_id in chunkList) { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWorker), new arguments { chunk_id = chunk_id }); } Console.ReadLine(); } static void ThreadWorker(Object stateInfo) { arguments arguments = (arguments)stateInfo; Console.WriteLine("Chunk # : {0} is set to START", arguments.chunk_id); UpdateSQLdb(arguments.chunk_id, DateTime.Now, null, null, "START", null, null); Random random = new Random(); int mseconds = random.Next(1, 10) * 1000; System.Threading.Thread.Sleep(mseconds); Console.WriteLine("Chunk # : {0} is sleeping for {1} sec.", arguments.chunk_id, mseconds); Console.WriteLine("Chunk # : {0} ist set to END", arguments.chunk_id); UpdateSQLdb(arguments.chunk_id, null, DateTime.Now, null, "END", null, null); } struct arguments { public Int64 chunk_id; } static void UpdateSQLdb(Int64 CHUNK_ID, DateTime? START_TS = null, DateTime? END_TS = null, Enum CHUNK_STATUS = null, string error_messages = null, byte? NEW_CALCULATION_ATTEMPTS = null, byte? NEW_POSTPROCESS_ATTEMPTS = null) { using (SqlConnection conn = new SqlConnection("Data Source=C55S01;Initial Catalog=MCS_BATCH;Integrated Security=SSPI;Asynchronous Processing=True")) //Timeout=60;Max Pool Size=200;Pooling=True; { int result = -1; conn.Open(); //<-- Each time I open a connection. It creates a new instead of reusing one from the ConnectionPool try { using (SqlCommand cmd = new SqlCommand("TEST.UpdateSQL", conn)) { cmd.CommandTimeout = 300; cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.Parameters.Add("@CHUNK_ID", SqlDbType.BigInt, 15).Value = CHUNK_ID; cmd.Parameters.Add("@START_TS", SqlDbType.DateTime2, 7).Value = START_TS; cmd.Parameters.Add("@END_TS", SqlDbType.DateTime2, 7).Value = END_TS; cmd.Parameters.Add("@ERR_MESSAGE", SqlDbType.VarChar).Value = error_messages; cmd.Parameters.Add("@ReturnValue", System.Data.SqlDbType.Int, 4).Direction = System.Data.ParameterDirection.ReturnValue; try { result = cmd.ExecuteNonQuery(); int return_value = (int)cmd.Parameters["@ReturnValue"].Value; if (return_value != 0) { Console.WriteLine("1. Error in running TEST.UpdateSQL, return value is : {0}", cmd.Parameters["@ReturnValue"].Value); } } catch (SqlException ex) { UpdateSQLdb(CHUNK_ID, null, DateTime.Now, null, ex.Message.ToString(), null, null); Console.WriteLine("2. Error executing TEST.UpdateSQL : {0}", ex); } } } catch (Exception ex) { Console.WriteLine("3.Error in TEST.UpdateSQL : {0}", ex); throw; } if (conn.State == ConnectionState.Open) { Console.WriteLine("Closing connection...."); conn.Close(); } conn.Dispose(); } } }
}
Моя проблема что я получил System.InvalidOperationException был необработанным (Истекло время ожидания ожидания). Период ожидания истекает до получения соединения из пула. Возможно, это произошло из-за того, что все объединенные соединения использовались и был достигнут максимальный размер пула.)
Я отслеживал количество подключений на SQL-сервере и быстро добирался до 100 подключений соединений в пуле)
Если попытались добавить эти параметры в строке соединения: Timeout = 60" Максимальный размер пула = 200; Pooling = True;
Но это будет просто отложить проблему на более поздний этап, потому что пул соединений достигнет 200, а таймаут будет достигнут в какой-то момент.
Вопрос: Почему соединения создаются снова и снова, вместо повторного использования одного из пула соединений?
Подсказка, советы и рекомендации приветствуются.
Вы пытаетесь запустить 500 одновременных процессов на 100 соединениях. Как вы думаете, что это возможно? Пул соединений SQL не может одновременно запускать две (или три или четыре) команды в одном и том же соединении. Это не то, что связывает объединение. – EkoostikMartin
Маловероятно, что ваше сетевое подключение действительно имеет возможность идти в ногу с таким количеством одновременных запросов.Вы почти наверняка не должны иметь столько потоков или много соединений, если это не большой сервер с большим количеством ресурсов, поддерживающих его. – Servy
Это хороший вопрос. После использования вы безопасно удаляете соединение. Использование вами объекта соединения используется только на время одного вызова. Объединение должно работать нормально. При подключении к пулу зависит от тайм-аута. Это не означает, что соединение отсутствует. Это должно работать отлично, если все соединения хранятся в течение небольшого промежутка времени. Исследуйте, почему соединения хранятся в течение длительного времени. – usr