首页 文章

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

提问于
浏览
10

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

enter image description here

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

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

我们使用的连接字符串:

Data Source = [server] .database.windows.net; initial catalog = [database]; persist security info = True; user id = [user]; password = [password]; MultipleActiveResultSets = True; Connection Timeout = 30; Max Pool Size = 200; Pooling = True; App = [AppName]

How is that possible taking into account connection pool limitation of 200 connections?

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

2 回答

  • 2

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

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

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

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

    连接泄漏 .

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

    在这种情况下,您不会在服务器上看到任何等待或阻塞 . Session 都将闲置,而不是等待 . 并且不会有大量的请求

    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使用率很低 .

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

  • 4

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

    首先,您是从代码创建dbcontext . 检查dbcontext对象的每个创建范围周围是否有using语句 . 就像是:

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

    这将在它自动超出范围时处置上下文 .

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

    services.AddScoped<xxxContext>(
    

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

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

相关问题