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
の最大プールサイズは1 です。
ここでの修正は、アプリケーションと連携して、特定の接続プールで接続がまだ「アクティブ」であるため、接続がクリーンアップされていない理由を見つけることです。使用するプール内の非アクティブな接続。
接続を解放して「非アクティブ」としてマークするには、アプリケーションがSqlConnection.Close()
またはSqlConnection.Dispose()
を呼び出す必要があります。
広範なブログ投稿(SQL Server DBAの接続プーリング))を接続プーリングについて書きました 何が表示されているのか、およびプログラムによる問題の修正について説明します。
代わりに、大量のレコードを処理している場合、実際には誤解を招くエラーが発生する可能性があります。 PCのすべてのポートを使い果たした可能性があります。Sysinternals TCPView を実行してこれを確認できます。
何千もの TIME_WAIT が表示される場合、これは考えられる原因です。
本質的に、アプリケーションがデータベースへの接続を閉じた後(using (var connection = new SqlConnection(_settings.DatabaseConnectionString))
の終わり)、TCPは、使用中のポートが解放される前に約4分間待機します再び使用されます。
これを実行するには、メモリから約16,000回の実行を4分未満で処理する必要があります(OSのバージョンと、そのPCで実行している他のものによって異なります)。