公司有个主数据库最近才从sqlserver2000升级到2008r2,性能提高了不少,也很少发生死锁。不过运转了快一个月的时候,发现个问题,内存居高不下,64G的内存,几乎被占用100%,结果差点把服务器给拖垮了。
看了网上不少文章归纳起来如下:
1.sqlserver缓存会一直增长到极限不释放。
2.要从自带的studio 连接,,在数据库服务器名称上点击【右键】,选择【属性】,然后,找到【内存】选项,在右边的【使用AWE分配内存】(sqlServer64的应该不用勾)左边把对勾打上。在最大服务器内存(MB)上填入适当的大小(具体填多大,肯定不能超过计算机的物理内存)
结果我兴匆匆的将最大值改成了55 296M(54G),内存一点变化也没有,设置再小的也没用。而且我还重启了一次,虽然重启后在启动,内存很小,但是过了一天时间,内存又涨到了96%。
弄得我百思不得其解,甚至差点相信网上说的2008r2的缓存机制有硬伤。
后来我又盯着设置内存的界面看了几遍,终于恍然大悟,嗨,这sqlserver坑爹啊,不设定sqlserver本身内存多少,他设定的是服务器的最大最小量。这还考起了人的阅读理解来了!于是我设定如下:
把内存的最小值设定了以后,服务器不需要重启,sqlserver的占用以肉眼可见的速度往下下降。内存占用下降到大概80%左右。
真是令人鼓舞啊。
也就是说设定了服务器占用内存最小的量,那么sqlserver最起码增长会留下最小量。
如果按照这么理解的话,最大服务器内存,就是约束服务器最大可以使用的内存,其他的都给sqlserver使用。
所以我继续做了一个测试,将最大服务器内存调整到16G。按照我的理解,这样的话,应该能保障sqlserver的内存拉满的话,应该一直在75%的水平线上运行,结果我失算了,设定完以后,sqlserver的内存又往下急剧下降,大概到了40%。也就是说,把最大服务器内存设小了,反而sqlserver能使用的内存上限也下来了。也就是这个最大服务器内存和最小服务器内存的设定,不是我所理解的线性关系。
我自己分析了下,毕竟sqlserver写数据的时候,是写在硬盘上,离不开消耗服务器的性能,在服务器内存够大的情况下,限定了服务器使用内存的上限,不仅限定了其他进程占用内存的上限,实际上也就等于限定了读写性能。所以最大服务器内存应该尽可能的大一些。我初步设定内存的80%。
如果这样理解的话,可以认为最大服务器内存,设定的是服务器本身的扩张上限(S_max),而最小服务器内存限定的是sqlserver扩张的上限(Total-S_min)
-------------------2021.11.24补充--------
按照我的理解和设置,SqlServer2008今天生产库的内存还是增长到94%,然后运行拖慢了,我将最大的设置值减小,让内存下来,数据库又畅快的运行了。看来的理解还是有误的。我用英文搜索了一些资料,在SqlServer官网得到一些答案,大神大致的意思是,现在设定的这个内存值只是一个buffer pool的范围大小,不代表SqlServer就占用这么多内存,实际上还有clr、锁页等消耗内存、ssis等没有计算在内。反正巴拉巴拉说了一堆,也没给个解决方案。只是得到一个建议,最好内存8G以上,也没什么卵用。我只好将内存上限设定的小一些,继续观测。有待持续观察。
-----------2021.12.11日补充----
发现内存还是在缓慢增长,本来理论上应该维持在80%的内存,最终还是突破了90%。无奈之下,只好继续查外文文献,输入关键查询 sql2008R2 memory leak,没想到这个竟然排在首位查询,还真找到些资料,
KB2778088 - FIX: Memory leak if you enable the AUTO_UPDATE_STATISTICS_ASYNC statistics option in SQL Server 2008, in SQL Server 2012 or in SQL Server 2008 R2
说是如果设置了自动统计功能,会有内存泄漏现象,并说微软有提供修复补丁,最后我找来找去,发现我现有数据库是sp2,可以直接升级到sp3,官方地址如下:https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=44271
于是在备机做了测试,能够顺利的升级,升级完需要重启。
原版本由 Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) 顺利升级到Microsoft SQL Server 2008 R2 (SP3) - 10.50.6000.34 (X64) 版本。
是否能解决内存无节制增长问题,是否是内存泄漏,有待于观察。
-----------2022.1.27------------------
打完补丁过了这么久,一直没发结果,是因为,中间服务器被重启过。打完补丁后,效果还是很明显的,SqlServer过了一个多月,内存从设定的72%增长到80%多,备机没有重启过,打了补丁经历了两个多月,因为没有设定内存上线,SqlServer内存占用84%,感觉也合理。目前SqlServer内存的还在十分缓慢增加,我看了下,服务器本身其他服务也在缓慢增长,基本上是同比线性的。一直没时间搞服务器如何限定内存无限增长的问题,感觉下个关注点应该在服务器本身。等有时间再优化下。现在已经基本不用担心SqlServer把服务器内存撑爆,但还达不到无人值守。
-----------2022.3.26------------------
经过实际观察,这个补丁打的有效,SqlServer内存维持在当初设定的72%,整体服务器的内存现在到了89%。SqlServer内存增长的问题已经无需担心了
-------2022.7.14------
调整完SqlServer内存后,因为window本身的服务内存每天悄悄增长0.1%,最后内存也满了,所以只好对SqlServer内存的上线往下调整了下,把内存先释放下去。像如下这样子。
能够看到这些服务在一个进程号里:
后来查了些资料,从官方得到一个监测内存的工具,ProcessExplorer,能花花绿绿的看到很详细的东西,不过还是没有解决方案
后来还是去官方,看到一点建议,说是可以把一个进程号的进程全部分离出来,然后逐个观察,到底哪个会消耗内存。于是乎,我执行了一堆如下命令,把能分离的都做了分离,不过有一些提示失败。弄完了以后,需要重启,但是数据库又不能宕机。所以暂时搁置了。
C:\Users\Administrator>sc config seclogon type= own
[SC] ChangeServiceConfig 成功
C:\Users\Administrator>sc config SENS type= own
[SC] ChangeServiceConfig 成功
C:\Users\Administrator>sc config SessionEnv type= own
[SC] ChangeServiceConfig 成功
C:\Users\Administrator>sc config ShellHWDetection type= own
[SC] ChangeServiceConfig 成功
C:\Users\Administrator>sc config Themes type= own
[SC] ChangeServiceConfig 成功
C:\Users\Administrator>sc config UserManager type= own
[SC] ChangeServiceConfig 成功
C:\Users\Administrator>sc config Winmgmt type= own
[SC] ChangeServiceConfig 成功
后来,我已经忘记了这个事情。头一个月对机房维护,重启了数据库,我突然想起来我分离服务这件事情。本来没报多大希望,结果发现服务分离以后,内存最近一直比较稳定。不像以前每天肉眼可见内存增加0.1%.有点意外。。。准备再观察一个月再说。
----------2022.10.4----------
不知不觉已经过了快三个月了,自从把服务分离以后,服务本身的内存也不自增长了,内存一直稳定在80%附近运行。看来以上的方法是有效的。
总结一下:
1. 针对SqlServer2008 数据库,首先打sp3补丁(上面已经有放链接)
2.针对服务器本身内存增长,可以通过微软提供的dos命令,进行服务分离,重启后进行观察分析(有可能有些服务不让分离,分离不开可能问题不大)。笔者是分离完之后,服务就没有再增长了。