如何保护SQL Server免受Linux上的OOM-killer杀掉

 今天机缘巧合搜到一篇微软CSS团队的一篇案例分享,在本人学习SQL On Linux过程中,对很多知识点存在不理解,看了这篇文章之后,觉得很有必要存起来,不管有没有其他人看,对我自己还是很有用,所以决定翻译一下,我相信在不久的将来这篇文章会被重视,因为SQL On Linux已经出来了一段时间,并且部分客户已经在用,国内市场的改变也只是时间上的问题。

 这是一篇关于SQL Server运行在Linux环境下的异常Failover场景的案例,下面是译文,读者如有兴趣可以阅读原文:How to safeguard SQL Server on Linux from OOM-Killer

 Windows平台上,当所有可用内存包括页文件(page file)被消耗干净,那么服务器的性能就会严重下降同时事件日志(event log)会记录OOMout of memory)错误。在Linux平台,这种行为就略微不同,当服务器运行在低可用内存情况下,Linux内核会选择某个可被杀掉(kill)的进程进行清除以便恢复系统的平稳运行。这个Linux上的机制称为OOM-Killer。

 对于SQL Server所在的服务器,SQL Server这种比其他进程消耗更多内存的进程很可能成为被优先杀掉的对象(oom-score记录了可能要被杀掉的进程的得分,从高到底进行kill)。本文将回顾一个客户场景,它强调了在Linux上安装SQL Server后,需要进行额外的配置调整。


 SQLServer技术支持组最近收到一个客户案例,情景如下:

  • Red hat企业版(RHEL)上运行SQL Server 2017
  • 服务器安装了12G内存
  • 以默认配置安装SQL Server
  • 部分数据库已配置AlwaysOn可用性组。集群是附加在Pacemaker之上的Red hat企业版RHELHA

 现状是:当在一个大表(大概25G)在进行索引重建时,重建操作被终止,同时可用性组Failover到其他副本。在进行深入研究后发现SQL Server进程在重建索引操作运行时被终止并导致Failover

 为了定位异常关闭的原因,我们检查了Linux系统日志(RHEL/var/log/messages)和pacemaker日志。从日志中看出到oom-killer被调用,然后导致SQL Server进程被终止。

 下面是pacemaker日志的部分内容,在/var/log/messages文件中也能看到类似内容:


Sep 13 16:17:30 l99s0004kernel: [9264025.516359] sqlservr invoked oom-killer:gfp_mask=0x280da, order=0, oom_score_adj=0 

Sep 13 16:17:30 l99s0004kernel: [9264025.516555] 184007 total pagecache pages

Sep 13 16:17:30 l99s0004kernel: [9264025.516556] 0 pages in swap cache

Sep 13 16:17:30 l99s0004kernel: [9264025.516558] Swap cache stats: add 0, delete 0, find 0/0

Sep 13 16:17:30 l99s0004kernel: [9264025.516558] Free swap  = 0kB

Sep 13 16:17:30 l99s0004kernel: [9264025.516559] Total swap = 0kB

Sep 13 16:17:30 l99s0004kernel: [9264025.516560] 3145598 pages RAM

 

注意:加粗部分代表服务器没有配置swap file

 

同时日志也包含了在OOM-Killer发起时所有系统进程的内存消耗快照。下面是整理过格式的结果:


Pid

Uid

Tgid

Total_vm

Rss

Nr_ptes

Swapents

Oom_score_adj

name

46206

0

46206

26370

247

54

0

-1000

Sshd

33492

992

33492

49412

3805

46

0

0

Sqlservr

33495

992

33495

3029788

2418852

5059

0

0

Sqlservr

 

注意:加粗部分的数值是在4K页,Rss列(内存使用)的SQL Server进程接近9448MB2418852*4/1024

 此外还有:


Sep 13 16:17:30 l99s0004kernel: [9264025.516658] Out of memory: Kill process 33495 (sqlservr) score 799or sacrifice child

Sep 1316: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 l99s0004kernel: sqlservr invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0

 

 上面加粗部分可以看到SQL Server有一个anon-rss9675408kB代表着“resident set size”,这是当前分配给进程的RAM部分。File-rss是系统所有进程在swap file(交换文件)中的内存量为0KB

 

 SQL Server启动时,SQL Server可用的物理内存数有memory.memorylimitmb配置来控制,默认为物理内存的80%,基于这个设置,SQL Serveranon-rss9675408KB(约为12GB80%)是有意义的,因为服务器有12GB内存。

 

 这个值在SQL Server启动时的错误日志信息中也能看到:

2017-09-1316:23:17.62 Server Detected 9478 MB of RAM. This is an informational message;no user action is required.

 

 在默认配置中,SQL Server可以使用大约12GB80%9.5GB的内存(服务器安装内存)。也就是留了大概2.5GB内存给服务器用于Linux内核和其他进程运行。首先,SQL Server仅用了9.5GB的一部分,在系统上保留了大量可用的内存。但是在重建索引运行时,SQL Server使用了所有可用的9.5GB的内存(译者注:索引重建理论上需要1~1.2倍左右的临时存储空间,而大部分处于内存的缓存当中,25G的表显然足够撑爆9.5G内存)。这时候就引起了Linux服务器只剩下很少内存可用,导致触发了OOM-Killer。作为当前最高内存使用进程(oom分数最高)的SQL Server就被当作牺牲者杀掉,

 

为了减少SQL ServerOOM影响,建议使用下面的一个或者两个:

  1. 调整memory.memorylimitmb配置以便即使SQL Server使用了所有的配置内存也还有足够的内存供操作系统运行。
  2. 确保swap文件存在并大小合理。

在这个客户场景中,通过设置memory.memorylimitmb6GB或者创建swap文件并调整大小来避免了oom-killer再次运行。



译者注:如果MSSQL进程突然挂了,可以用dmesg查看是否有OOM


你可能感兴趣的:(数据库管理,SQL,on,Linux,SQL,On,Linux)