首页 > 解决方案 > Azure SQL 数据库上的奇怪池行为

问题描述

这个问题是关于 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 层限制为 600 个连接。

我们使用 API 在数据库中生成一些数据。此 API 调用 3 个不同的 SQL 命令而不共享连接(sqlCommand.Connection为空所以closeConnection == true

现在的问题:在本地 SQL Server 上,一切正常:我们总是有 45-46 个连接处于睡眠状态,所以池工作正常,没问题,我们可以在数据库中生成数千个项目。

但在 Azure DB 中,池的工作方式非常不同。看起来池化根本不起作用。Max Pooling 完全被忽略:在对象生成过程中,连接总数很快达到了我们层的限制(600),我们得到了错误:

数据库的会话限制为 600 并且已达到。请参阅“ http://go.microsoft.com/fwlink/?LinkId=267637 ”以获得帮助。

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'

标签: sql-serverazureazure-sql-databasepooling

解决方案


推荐阅读