Active Azure Sql连接超出了连接池限制

时间:2017-06-24 04:27:00

标签: c# sql-server azure entity-framework-6 connection-pooling

我们的Azure SQL数据库性能会在很长一段时间内显着降低,我们会在生产中解决问题。我们知道我们在其中一个表上有锁,但是这些锁不是死锁,它们是长锁,并且在一个小时左右的时间内性能恢复正常。我们试图找到关于如何获得这些长锁的所有可能场景(每个查询都超快,所有性能分析器都可以向我们展示导致长锁的原因)。这个问题的原因如下图所示:

enter image description here

输出连接池设置仅允许合并200个连接。大多数时候,我们与数据库有大约10-20个开放/池化连接。然后突然一些活动连接开始增长,池完全被占用。虽然许多池化连接保持在200以下,但我们看到使用sp_who2的多个活动连接达到1.5k-2k连接(有时为4k-5k)。

我使用Azure门户监控工具构建了相同的图表。它有不同的聚合期,但显示相同的问题: enter image description here

我们使用的连接字符串:

  

数据源= [服务器] .database.windows.net;初始   catalog = [database]; persist security info = True;用户   ID = [用户];密码= [口令]; MultipleActiveResultSets = TRUE;连接   超时= 30;最大池大小= 200;池=真; App = [AppName]

如何考虑200个连接的连接池限制?

ps:没有周期性任务,长时间运行的查询或其他任何工具,我们检查了sp_who2与数据库的所有活动连接。

3 个答案:

答案 0 :(得分:6)

[这是一个长期评论而不是答案]

  

我确实有几台主机连接到同一个数据库,但每台主机都有200个连接的相同限制

连接池为per(连接字符串,AppDomain)。每个服务器可能有多个AppDomain。每个AppDomain每个连接字符串都有一个连接池。因此,如果您有不同的用户/密码组合,它们将生成不同的连接池。所以没有真正的谜团,为什么有200多个连接可能。

那你为什么要得到很多联系呢?可能的原因:

连接泄漏。

如果您未能处理DbContext或SqlConnection,那么连接将在托管堆上停留,直到最终完成,并且无法重用。当连接池达到其限制时,新连接请求将等待30秒以使连接可​​用,并在此之后失败。

在这种情况下,您不会在服务器上看到任何等待或阻止。会议都将闲置,而不是等待。

中不会有大量请求
select *
from sys.dm_exec_requests 

请注意,会话等待统计信息现在可以在Azure SQL DB上运行,因此更容易看到实时阻止和等待。

select *
from sys.dm_exec_session_wait_stats

阻止。

如果传入请求开始被某个事务阻止,并且新请求不断启动,则会话数会增加,因为新请求会获得新会话,启动请求并被阻止。在这里你会看到很多被阻止的请求

select *
from sys.dm_exec_requests

慢查询。

如果请求由于资源可用性(CPU,磁盘,日志)而需要很长时间才能完成,您可以看到这一点。但这不太可能,因为在此期间您的DTU使用率很低。

因此,下一步是查看这些连接是否在服务器上处于活动状态,表明在服务器上阻塞或空闲,表明存在连接池问题。

答案 1 :(得分:2)

有两件事可以检查dbcontext对象,看看你是否正确使用它们并配置对象以返回连接池的连接。

首先,您要从代码创建dbcontext。检查dbcontext对象的每个创建范围周围是否有using语句。类似的东西:

using (var context = new xxxContext()) {
    ...
}

当它自动超出范围时,这将处理上下文。

其次,您使用依赖注入来注入dbcontext对象。确保使用作用域:

services.AddScoped<xxxContext>(

然后DI将负责处理您的上下文对象。

您可以检查的下一件事是您是否有未提交的交易。检查您的所有事务是否都在使用块中,因此当您超出范围时,它们将提交或回滚。

答案 2 :(得分:1)

问题可能与“ 游泳池碎片

有关

池碎片化是许多Web应用程序中的常见问题,在这些Web应用程序中,应用程序可以创建大量的池,直到进程退出时才释放这些池。这会导致大量连接打开并占用内存,从而导致性能下降。

由于集成安全性造成的池碎片* 根据连接字符串加上用户身份来合并连接。因此,如果您在网站上使用基本身份验证或Windows身份验证以及集成的安全性登录名,则每个用户获得一个池。尽管这可以提高单个用户后续数据库请求的性能,但是该用户无法利用其他用户建立的连接。这还会导致每个用户至少有一个与数据库服务器的连接。这是特定Web应用程序体系结构的副作用,开发人员必须权衡安全性和审核要求。

来源https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling