在基于Windows的服务器上,当包括页面文件在内的所有可用内存都被占用时,服务器的性能会变得缓慢,并且会将内存不足错误记录到事件日志中。在Linux系统上,行为稍有不同。当服务器内存不足时,Linux内核将选择一个进程被终止,以恢复系统的平稳运行。Linux上的这种机制叫做OOM-Killer。更多信息请访问https://linux-mm.org/OOM_Killer
在运行SQL Server的服务器上,杀死的进程可能很可能是SQL Server进程,因为与其他进程相比,预计会有更大的内存占用。在这个博客中,我们将回顾一个客户场景,强调在Linux上安装SQL Server之后,需要执行额外的配置调整。
SQL Server支持团队最近有以下客户方案。
- 客户在Redhat企业Linux服务器上运行SQL Server 2017。
- 服务器有12GB的RAM。
- SQL Server安装了默认配置。
- 有些数据库是Alwayson Availability组的一部分。集群层基于在Pacemaker之上构建的红帽企业Linux(RHEL)HA插件。
当索引重建在大型表(大约25GB)上启动时,reindex操作终止,可用性组故障转移到另一个副本。
经过进一步调查,我们发现SQL Server进程在运行reindex操作时终止,并导致故障转移。
查看了Linux系统日志(/var/log/messages on RHEL)以及pacemaker日志,从日志中可以看出oom-killer已经启动, 并将sql server进程终止.
详细的数据参考:
Sep 13 16:17:30 l99s0004 kernel: [9264025.516359] sqlservr invoked oom-killer: gfp_mask=0x280da, order=0,oom_score_adj=0
Sep 13 16:17:30 l99s0004 kernel: [9264025.516555] 184007 total pagecache pages
Sep 13 16:17:30 l99s0004 kernel: [9264025.516556] 0 pages in swap cache
Sep 13 16:17:30 l99s0004 kernel: [9264025.516558] Swap cache stats: add 0, delete 0, find 0/0
Sep 13 16:17:30 l99s0004 kernel: [9264025.516558] Free swap = 0kB
Sep 13 16:17:30 l99s0004 kernel: [9264025.516559] Total swap = 0kB
Sep 13 16:17:30 l99s0004 kernel: [9264025.516560] 3145598 pages RAM
注意:突出红色的条目表示在服务器上没有配置交换文件。
日志还显示了调用oom-killer时系统上所有进程的内存消耗快照。输出以表格形式显示,下面只有三个过程,以便于阅读。
注意:突出显示的数字是4K页面。SQL Server进程的Rss列(内存使用量)计算到大约9448MB((2418852 * 4)/ 1024)。
Sep 13 16:17:30 l99s0004 kernel: [9264025.516658] Out of memory: Kill process 33495 (sqlservr) score 799 or sacrifice child
Sep 13 16:17:30 l99s0004 kernel: [9264025.516709] Killed process 33495 (sqlservr) total-vm:12119152kB, anon-rss:9675408kB, file-rss:0kB, shmem-rss:0kB
Sep 13 16:17:30 l99s0004 kernel: sqlservr invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
可以看到SQL Server的anon-rss值为9675408kB.RSS代表“驻留集大小”,即当前在进程中为RAM分配的内存量。file-rss是交换文件中对于该系统中所有进程为0KB的内存量。
SQL Server启动时,SQL Server可用的物理内存量由memory.memorylimitmb配置选项控制,默认为物理内存的80%。基于此设置,SQL Server的匿名rss值为9675408kB(12GB的80%)是有意义的,因为服务器总共有12GB的RAM。
在启动过程中,也可以在SQL Server错误日志中看到这些信息。
2017-09-13 16:23:17.62服务器检测到9478 MB的RAM。这是一条信息性消息; 无需用户操作。
参考:https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-configure-mssql-conf#memorylimit
由于默认的配置设置,SQL Server可以在服务器上安装大约9.5GB的12GB RAM。这使服务器上的2.5GB内存被Linux内核和服务器上运行的其他进程所使用。首先,SQL Server只使用了9.5GB的一部分,在系统上留下了大量的内存。但是,执行索引重建时,SQL Server用尽了所有9.5GB的内存。这种情况导致Linux服务器上留下的内存很少,从而导致了OOM-killer的执行。SQL Server被Kill了,因为它具有最高的内存使用率(oom-score)。
为了使SQL Server不易受到此影响,我们推荐以下一个或两个建议。
(解决方法)
- 即使SQL Server要使用通过此设置配置的所有内存,也要仔细调整memory.memorylimitmb配置选项以在系统上留下足够的内存。
- 确保交换文件存在并正确调整大小。
在这个客户场景中,我们可以通过将memory.memorylimitmb设置为6GB 或者通过创建一个交换文件并将其设置为适当的大小来避免。
有关Linux上SQL Server 2017的其他最佳实践和配置指导,请参阅https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-performance-best-practices上的文档。