Этот вопрос касается очень странного поведения пула в базе данных SQL Azure.
Вот код для выполнения команд 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;
Наш уровень SQL Azure ограничен 600 подключениями.
Мы используем API для создания некоторых данных в базе данных.Этот API вызывает 3 разные команды SQL без совместного использования соединения (sqlCommand.Connection
является нулевым, поэтому closeConnection == true
)
Теперь проблема: на локальном SQL Server все работает нормально: у нас всегда 45-46 соединений в спящем состоянииТаким образом, пул работает нормально, нет проблем, мы можем сгенерировать тысячи элементов в базе данных.
Но в БД Azure пул работает совсем по-другому.Похоже, объединение не работает вообще.Максимальный пул полностью игнорируется: очень скоро во время генерации объектов общее число соединений достигает предела нашего уровня (600), и мы получаем ошибку:
Предел сеанса для базы данных равен 600 и был достигнут,См. 'http://go.microsoft.com/fwlink/?LinkId=267637' для получения помощи.
И команды SQL никогда не используют существующие соединения повторно, они остаются в спящем состоянии для стандартного времени клиента .net sql (~ 4 минуты).
У меня такое же поведение, даже когда моя локальная Service Fabric подключена к базе данных Azure.
Вопрос: почему это произошло и как этого избежать?
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'