This question is about very strange pooling behavior on Azure SQL database.
Here is the code to execute SQL commands:
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;
}
}
This method works inside Azure Service Fabric which can run in two modes: locally (running under Visual Studio and connected to SQL Server 2016) and in Azure with Azure SQL. Connection strings in each case are:
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;
Our Azure SQL Tier limited to 600 connections.
We using API to generate some data in database. This API calls 3 different SQL commands without sharing connection (sqlCommand.Connection
is null so closeConnection == true
)
Now the problem: on local SQL Server, everything works fine: we always have 45-46 connections in sleeping status, so pooling works fine, no problem, we can generate thousand of items in the database.
But in Azure DB, pooling works in a very different way. Looks like pooling doesn't work at all. Max Pooling totally ignored: very soon during objects generation the total number of connections reach limit of our tier (600) and we got the error:
The session limit for the database is 600 and has been reached. See 'http://go.microsoft.com/fwlink/?LinkId=267637' for assistance.
And SQL commands never re-use the existing connections, they are remaining in status sleeping for default .net sql client time (~4 minutes).
I have same behavior even when my local Service Fabric connected to Azure DB.
Question: why this happened and how to avoid?
PS: I'm using this query to get connection count (sp_who
shows the same count):
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'