Sql-Server

目前所有連接都“超時”

  • January 21, 2020

我有一個連接到 SQL Server 的應用程序。目前我得到,

Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.

我跑的時候,

SELECT 
   DB_NAME(dbid) as DBName, 
   COUNT(dbid) as NumberOfConnections,
   loginame as LoginName
FROM
   sys.sysprocesses
WHERE 
    DB_NAME(dbid) ='MyDb'
GROUP BY 
   dbid, loginame 

DBName  NumberOfConnections LoginName
MyDb    10                     sa                                                                                                                              
MyDb    109                   MyUser

所有程序的狀態是sleeping,cms是AWAITING COMMAND

這是我的程式碼,

private async Task<object> ExecuteAsync<T>(ExecutionType executionType, CommandType commandType, string commandText, IsolationLevel isolationLevel, SqlParameter[] parameters, Func<IDataReader, T> callback = null)
{
   var stopwatch = new Stopwatch();
   stopwatch.Start();
   using (var connection = new SqlConnection(_settings.DatabaseConnectionString))
   {
       using (var command = new SqlCommand(commandText, connection) {CommandType = commandType})
       {
           command.Parameters.AddRange(parameters);
           await connection.OpenAsync().ConfigureAwait(false);
           command.CommandTimeout = _settings.CommandTimeout;
           var transaction = connection.BeginTransaction(isolationLevel);
           command.Transaction = transaction;
           try
           {
               object result;
               switch (executionType)
               {
                   case ExecutionType.Reader:
                       var reader = await command.ExecuteReaderAsync().ConfigureAwait(false);
                       using (reader)
                       {
                           var list = new List<T>();
                           while (reader.Read())
                           {
                               if (callback != null)
                               {
                                   var item = callback(reader);
                                   if (item != null)
                                   {
                                       list.Add(item);
                                   }
                               }
                           }
                           result = list;
                       }
                       break;
                   case ExecutionType.NonQuery:
                       result = await command.ExecuteNonQueryAsync().ConfigureAwait(false);
                       break;
                   default:
                       result = await command.ExecuteScalarAsync().ConfigureAwait(false);
                       break;
               }
               transaction.Commit();
               stopwatch.Stop();
               var elapsed = stopwatch.Elapsed;
               if (elapsed.Seconds > 2)
               {
                   _logger.Log(string.Format("{0} took {1} time", command.CommandText, elapsed));// only log if it tooks more than 2 seconds
               }
               return result;
           }
           catch (Exception exception)
           {
               _logger.Log(exception);
               transaction.Rollback();
               throw;
           }
       }
   }
}

看起來您的應用程序沒有正確關閉或處理SqlConnection對象。預設情況下,SqlConnection最大池大小為 100

這裡的解決方法是與應用程序一起找出連接沒有被清理的原因,因為它們在特定的連接池中仍然是“活動的”,這就是你無法獲取另一個連接的原因,因為沒有要使用的池中的非活動連接。

應用程序應該呼叫SqlConnection.Close()SqlConnection.Dispose()以釋放連接並將其標記為“非活動”。

我寫了一篇關於連接池的廣泛部落格文章(SQL Server DBA 的連接池),它應該闡明為什麼你會看到你所看到的,以及對這個問題的程式修復。

另一種選擇是,如果您正在處理大量記錄,您實際上可能會遇到誤導性錯誤。可能是您已經用完了 PC 上的所有埠,您可以通過執行 Sysinternals TCPView來檢查這一點。

如果您看到數千個TIME_WAIT,這是一個可能的原因。

本質上,在您的應用程序關閉與數據庫的連接後(在 結束時using (var connection = new SqlConnection(_settings.DatabaseConnectionString))),TCP 將等待近 4 分鐘,然後才能再次使用正在使用的埠。

從記憶體中,您需要在 4 分鐘內處理大約 16,000 次執行才能發生這種情況(這取決於您的作業系統版本以及您在該 PC 上執行的其他內容)。

引用自:https://dba.stackexchange.com/questions/81372