今天机缘巧合搜到一篇微软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)会记录 OOM ( out 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 S erver
- 部分数据库已配置 AlwaysOn 可用性组。集群是 附加在 Pacemaker 之上的 Red hat 企业版 ( RHEL ) HA 。
现状是: 当在一个大表(大概 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 页, R ss 列(内存使用)的 SQL Server 进程接近 9448MB ( 2418852*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-rss 值 9675408kB 代表着“ resident set size ”,这是当前分配给进程的 RAM 部分。 File-rss 是系统所有进程在 swap file (交换文件)中的内存量为 0KB 。
当 SQL Server 启动时, SQL Server 可用的物理内存数有 memory.memorylimitmb 配置来控制,默认为物理内存的 80% ,基于这个设置, SQL Server 的 anon-rss 值 9675408KB (约为 12GB 的 80 % )是有意义的,因为服务器有 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 可以使用大约 12GB 的 80% 即 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 S erver 被 OOM 影响,建议使用下面的一个或者两个:
- 调整 memory.memorylimitmb 配置以便即使 SQL Server 使用了所有的配置内存也还有足够的内存供操作系统运行。
- 确保 swap 文件存在并大小合理。
在这个客户场景中,通过设置 memory.memorylimitmb 为 6GB 或者创建 swap 文件并调整大小来避免了 oom-killer 再次运行。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。