use*_*567 4 sql-server ado.net
我有一个连接到 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.
Run Code Online (Sandbox Code Playgroud)
我跑的时候,
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
Run Code Online (Sandbox Code Playgroud)
所有进程的状态是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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
看起来您的应用程序没有正确关闭或处理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 上运行的其他内容)。