这个问题是关于Azure SQL数据库上非常奇怪的池行为。
以下是执行SQL命令的代码:
async Task ExecuteSqlQuery(SqlCommand sqlCommand, Action<SqlDataReader> dataReaderHandler = null)
{
try
{
// share execution between connections
Func<SqlConnection, bool, Task> doQuery = async (connection, closeConnection) =>
{
sqlCommand.Connection = connection;
if (connection.State != ConnectionState.Open)
await connection.OpenAsync();
using (var dataReader = await sqlCommand.ExecuteReaderAsync())
{
dataReaderHandler?.Invoke(dataReader);
}
if (closeConnection)
connection.Close();
};
if (sqlCommand.Connection != null)
{
await doQuery(sqlCommand.Connection, false);
sqlCommand.Dispose();
}
else
{
using (SqlConnection connection = this.connectionSettings.BuildConnection())
{
await doQuery(connection, true);
sqlCommand.Dispose();
}
}
}
catch (Exception er)
{
throw;
}
}
此方法适用于Azure Service Fabric,它可以在两种模式下运行:本地(在Visual Studio下运行并连接到SQL Server 2016)和Azure中使用Azure SQL。每种情况下的连接字符串都是:
Data Source=sqlLocal;Initial Catalog=SFDB;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=30;
Server=tcp:sqlazure.database.windows.net,1433;Initial Catalog=SFDB;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Max Pool Size=200;
我们的Azure SQL Tier限制为600个连接。
我们使用API在数据库中生成一些数据。此API在没有共享连接的情况下调用3个不同的SQL命令(sqlCommand.Connection
为空,因此closeConnection == true
)
现在的问题是:在本地SQL Server上,一切正常:我们总是有45-46个连接处于休眠状态,因此池工作正常,没问题,我们可以在数据库中生成数千个项目。
但是在Azure DB中,池的工作方式非常不同。看起来像汇集根本不起作用。 Max Pooling完全被忽略:在对象生成期间很快,连接总数达到了我们层(600)的极限,我们得到了错误:
数据库的会话限制为600且已达到。请参阅&#39; http://go.microsoft.com/fwlink/?LinkId=267637&#39;寻求帮助。
并且SQL命令永远不会重用现有连接,它们保持状态为默认.net sql客户端时间(约4分钟)。
即使我的本地Service Fabric连接到Azure DB,我也有同样的行为。
问题:为什么会发生这种情况以及如何避免?
PS:我使用此查询来获取连接数(sp_who
显示相同的数量):
SELECT c.session_id, s.status
FROM sys.dm_exec_connections AS c
JOIN sys.dm_exec_sessions AS s ON c.session_id = s.session_id
WHERE c.session_id <> @@SPID
AND s.status = 'sleeping'