0

问题

我在安装了单个数据库的客户 VM 上部署了 SQL Server 2017 数据库。该数据库有一个 Web 应用程序,在高峰时间连接到大约 100 个活跃用户。在过去的几个月里,客户不得不在使用 5 天后重新启动 sql server 实例,因为应用程序开始出现性能下降的迹象(有时一个页面需要一秒钟才能加载,而同一个页面可能需要 15 秒)。几个月来我一直在监视查询存储并对查询进行性能优化,但是我仍然无法阻止数据库在本周末遇到性能问题。

当问题出现时(正常运行 5 天后),尽管查询频率和运行查询的类型在一周内完全相同,但服务器显示 CPU 和内存使用率很高。在遇到问题时查看查询存储后,我没有看到任何长时间运行的查询,并且在 CPU 或内存分析图表上没有什么比我在应用程序运行正常时看到的更高。

我注意到的一件事是内部/默认资源池在一周内的使用量增加。重新启动后不久,资源池的使用率看起来很低: 在此处输入图像描述

5 天后,资源池看起来要高得多: 在此处输入图像描述

我注意到,当我运行查询时,资源池会在查询运行时增加,但在查询完成运行后总是会释放内存,这似乎在客户实例上没有正确发生,否则我不明白为什么资源池会随着时间的推移而增加。

问题

资源池使用量是否会随着时间的推移而增加,这可能会导致性能问题?

什么会导致资源池内存不被释放?

我为缓解我们一直面临的性能问题而实施的措施如下:

  1. 打开 READ_COMMITTED_SNAPSHOT 隔离,这有助于缓解应用程序由于锁定而出现无响应的问题。
  2. 设置最大服务器内存以确保它不会使操作系统处于饥饿状态。
  3. 花了几个月的时间优化一堆查询以减少 CPU 持续时间和逻辑读取,还添加了索引,这有一定帮助,但并没有解决我的所有问题。
4

1 回答 1

0

我相信我已经找到了这个问题的罪魁祸首。用于连接数据库和执行查询的 sqljdbc4.2.jar 存在内存泄漏。在运行应用程序的负载测试并监控 sys.dm_os_memory_clerks 之后,我可以看到 MEMORYCLERK_SQLCONNECTIONPOOL pages_kb 随着越来越多的查询对数据库执行而增加。作为副作用,这也会增加资源池中的“已用内存”。

将 jdbc 库更新到更高版本后,MEMORYCLERK_SQLCONNECTIONPOOL 不会随时间增加。

<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
     <artifactId>mssql-jdbc</artifactId>
     <version>8.4.1.jre8</version>
</dependency>
于 2020-10-19T21:29:23.187 回答