Sql-Server
目前所有連接都“超時”
我有一個連接到 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 上執行的其他內容)。