【作者】

王栋:携程技术保障中心数据库专家,对数据库疑难问题的排查和数据库自动化智能化运维工具的开发有强烈的兴趣。

【问题描述】

我们知道当mysqld进程使用到SWAP时,就会严重影响到MySQL的性能。SWAP的问题比较复杂,本文会从SWAP的原理开始,分享我们碰到的案例和分析思路。

【SWAP原理】

swap是把一部分磁盘空间或文件,当作内存来使用。它有换出和换入两种方式,换出是进程把不活跃的内存数据存储到磁盘上,并释放数据占用的内存空间,换入是进程再次访问这部分数据的时候,从磁盘读到内存中。

swap扩展了内存空间,是为了回收内存。内存回收的机制,一种是当内存分配没有足够的空间时,系统需要回收一部分内存,称为直接内存回收。另外还有一个专门的kswapd0进程用来定期回收内存。为了衡量内存的使用情况,定义了三个内存阀值,分为页最小水位(min)、页低水位(low)、页高水位(high)

执行下面命令,可以看到水位线对应的值,如下图所示

cat /proc/zoneinfo |grep -E "Node|pages free|nr_inactive_anon|nr_inactive_file|min|low|high"|grep -v "high:"

内存回收行为主要有

1、当系统剩余内存低于low时,kswapd开始起作用进行内存回收,直到内存达到high水位。

2、当剩余内存达到min时就会触发直接回收。

3、当触发全局回收,并且file+free<=high时,一定会进行针对匿名页的swap。

【NUMA与SWAP】

有些案例我们发现系统还有大量剩余空间的情况下,已经使用了swap。这正是NUMA架构导致的。NUMA架构下每个Node都有本地的内存空间,Node间内存使用不均衡,当某个Node的内存不足时,就可能导致swap的产生。

【swappiness】

我们大概理解了内存回收的机制,回收的内存包括文件页和匿名页。对文件页的回收就是直接回收缓存,或者把脏页写回到磁盘再进行回收。对匿名页的回收,就是通过swap,将数据写入磁盘后再释放内存。

通过调整/proc/sys/vm/swappiness的值,可以调整使用swap的积极程度,swappiness值从0-100,值越小,倾向于回收文件页,尽量少的使用swap。我们最初将这个值调整为1,但发现并不能避免swap的产生。实际上即使将这个值设置0,当满足file+free<=high时,还是会发生swap。

【关闭NUMA的方案】

在NUMA开启的情况,由于NUMA节点间内存使用不均衡,可能导致swap,解决这个问题主要有下面一些方案

1、 在mysqld_safe脚本中加上“numactl –interleave all”来启动mysqld
2、 Linux Kernel启动参数中加上numa=off,需要重启服务器
3、 在BIOS层面关闭NUMA
4、 MySQL 5.6.27/5.7.9开始引用innodb_numa_interleave选项

对于2、3、4关闭NUMA的方案比较简单,不做详细描述,下面重点描述下方案1

【开启numa interleave访问的步骤】

1、 yum install numactl -y
2、修改/usr/bin/mysqld_safe文件
cmd="`mysqld_ld_preload_text`$NOHUP_NICENESS"下新增一条脚本
cmd="/usr/bin/numactl --interleave all $cmd"
3、service mysql stop
4、写入硬盘,防止数据丢失
sync;sync;sync
5、延迟10秒
sleep 10
6、清理pagecache、dentries和inodes
sysctl -q -w vm.drop_caches=3
7、service mysql start
8、验证numactl –interleave all是否生效,可以通过下面命令,interleave_hit是采用interleave策略从该节点分配的次数,没有启动interleave策略的服务器,这个值会很低
numastat -mn -p `pidof mysqld`

至此我们MySQL5.6的服务器通过上面方案解决了由于NUMA Node间内存分配不均导致的swap的问题。对于MySQL5.7.23版本的服务器,我们使用了innodb_numa_interleave选项,但问题并没有彻底解决。

【使用MySQL5.7新增innodb_numa_interleave选项的问题】

在开启innodb_numa_interleave选项的服务器中,仍然会存在NUMA Node间内存分配不均衡的问题,会导致swap产生。针对这个问题做了进一步分析:

1、 MySQL 版本为5.7.23,已经开启了innodb_numa_interleave

2、 使用命令查看mysqld进程的内存使用情况,numastat -mn `pidof mysqld`

可以看出Node 0使用了约122.5G内存,Node 1使用了约68.2G内存,其中Node0上的可用空间只剩566M,如果后面申请Node 0节点分配内存不足,就可能产生swap

Per-node process memory usage (in MBs) for PID 1801 (mysqld)
Node 0 Node 1 Total
--------------- --------------- ---------------
Huge 0.00 0.00 0.00
Heap 0.00 0.00 0.00
Stack 0.01 0.07 0.09
Private 125479.61 69856.82 195336.43
---------------- --------------- --------------- ---------------
Total 125479.62 69856.90 195336.52

3、是innodb_numa_interleave没有生效吗,通过分析/proc/1801/numa_maps文件可以进一步查看mysqld进程的内存分配情况

以其中一条记录为例,

7f9067850000    表示内存的虚拟地址
interleave:0-1 表示内存所用的NUMA策略,这里使用了Interleave方式
anon=5734148 匿名页数量
dirty=5734148 脏页数量
active=5728403 活动列表页面的数量
N0=3607212 N1=2126936 节点0、1分配的页面数量
kernelpagesize_kB=4 页面大小为4K
7f9067850000 interleave:0-1 anon=5734148 dirty=5734148 active=5728403 N0=3607212 N1=2126936 kernelpagesize_kB=4

4、通过解析上面文件,对Node 0和Node 1节点分配的页面数量做统计,可以计算出Node 0通过interleave方式分配了约114.4G内存,Node 1通过interleave方式分配了约64.7G内存

说明innodb_numa_interleave开关是实际生效的,但是即使mysql使用了interleave的分配方式,仍然存在不均衡的问题

5、通过innodb_numa_interleave相关的源码,可以看出当开关开启时,MySQL调用linux的set_mempolicy函数指定MPOL_INTERLEAVE策略跨节点来分配内存set_mempolicy(MPOL_INTERLEAVE, numa_all_nodes_ptr->maskp, numa_all_nodes_ptr->size)

当开关关闭时,set_mempolicy(MPOL_DEFAULT, NULL, 0),使用默认的本地分配策略

my_bool  srv_numa_interleave = FALSE;
\#ifdef HAVE_LIBNUMA
\#include
\#include
struct set_numa_interleave_t
{
set_numa_interleave_t()
{
if (srv_numa_interleave) {
ib::info() maskp,
numa_all_nodes_ptr->size) != 0) {
ib::warn()

【测试对比开启innodb_numa_interleave开关和numactl –interleave=all启动mysqld进程两种方式NUMA节点的内存分配情况】

场景一、numactl --interleave=all启动mysqld进程的方式

1、 修改systemd配置文件,删除my.cnf中innodb_numa_interleave=on开关配置,重启MySQL服务

/usr/bin/numactl --interleave=all /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS

2、 运行select count(*) from test.sbtest1语句,这个表中有2亿条记录,运行14分钟,会将表中的数据读到buffer pool中



3、运行结束后,分析numa_maps文件可以看到mysqld进程采用了interleave跨节点访问的分配方式,两个Node间分配的内存大小基本一致

7f9a3c5b3000 interleave:0-1 anon=1688811 dirty=1688811 N0=842613 N1=846198 kernelpagesize_kB=4
7f9a3c5b3000 interleave:0-1 anon=2497435 dirty=2497435 N0=1247949 N1=1249486 kernelpagesize_kB=4

4、mysqld进程总的分配也是均衡的

场景二、开启innodb_numa_interleave的方式

1、增加my.cnf中innodb_numa_interleave=on开关配置,重启MySQL服务,执行与场景一相关的SQL语句

2、运行结束后,分析numa_maps文件可以看到mysqld进程采用interleave方式分配的在不同Node间是基本平衡的

7f71d8d98000 interleave:0-1 anon=222792 dirty=222792 N0=111652 N1=111140 kernelpagesize_kB=4
7f74a2e14000 interleave:0-1 anon=214208 dirty=214208 N0=107104 N1=107104 kernelpagesize_kB=4
7f776ce90000 interleave:0-1 anon=218128 dirty=218128 N0=108808 N1=109320 kernelpagesize_kB=4

3、不过仍有部分内存使用了default的本地分配策略,这部分内存全部分配到了Node 0上

7f31daead000 default anon=169472 dirty=169472 N0=169472 kernelpagesize_kB=4

4、最终mysqld进程分配的内存Node 0 比Node 1大了约1G

【MySQL5.7.23启用numactl –interleave=all的方法】

MySQL5.7版本不再使用mysqld_safe文件,所以启用numactl –interleave=all的方式,与MySQL 5.6的方法不同,总结如下:

1、修改vim /etc/my.cnf文件,删除innodb_numa_interleave配置项
2、修改systemd 的本地配置文件,vim /usr/lib/systemd/system/mysqld.service,增加/usr/bin/numactl --interleave=all命令
# Start main service
ExecStart=/usr/bin/numactl --interleave=all /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS
3、停止MySQL服务
systemctl stop mysqld.service
4、重新加载配置文件
systemctl daemon-reload
5、写入硬盘,防止数据丢失
sync;sync;sync
6、延迟10秒
sleep 10
7、清理pagecache、dentries和inodes
sysctl -q -w vm.drop_caches=3
8、启动MySQL服务
systemctl start mysqld.service
9、验证是否生效,
首先确认show global variables like ' innodb_numa_interleave';开关为关闭状态
正常情况下mysqld进程会全部采用interleave跨节点访问的分配方式,如果可以查询到其他访问方式的信息,表示interleave方式没有正常生效
less /proc/`pidof mysqld`/numa_maps|grep -v 'interleave'

【结论】

numactl –interleave=all启动mysqld进程的方式NUMA不同Node间分配的内存会更加均衡。

这个差异是与innodb_numa_interleave参数执行的策略有关,开启后,全局内存采用了interleave的分配方式,但线程内存采用了default的本地分配方式。

而如果使用numactl –interleave=all启动mysqld进程,所有内存都会采用interleave的分配方式。

NUMA导致的MySQL服务器SWAP问题分析的更多相关文章

  1. NUMA导致的MySQL服务器SWAP问题分析与解决方案

    [SWAP产生原理] 先从swap产生的原理来分析,由于linux内存管理比较复杂,下面以问答的方式列了一些重要的点,方便大家理解: 1.swap是如何产生的 swap指的是一个交换分区或文件,主要是 ...

  2. MySQL服务器发生OOM的案例分析

    [问题] 有一台MySQL5.6.21的服务器发生OOM,分析下来与多种因素有关 [分析过程] 1.服务器物理内存相对热点数据文件偏小,62G物理内存+8G的SWAP,数据文件大小约550G 触发OO ...

  3. MySQL针对Swap分区的运维注意点

    Linux有很多很好的内存.IO调度机制,但是并不会适用于所有场景.对于运维人员来说,Linux比较让人头疼的一个地方是:它不会因为MySQL很重要就避免将分配给MySQL的地址空间映射到swap上. ...

  4. 利用innodb_force_recovery 解决WAMP MySQL服务器无法正常启动的问题

    有次公司突然断电,导致wamp mysql无法重启 二 分析    初步估计是mysql日志损坏问题,从日志内容分析来看,数据库在机器crash 导致日志文件损坏,重启之后无法正常恢复,更无法正常对外 ...

  5. MySQL大事务导致的Insert慢的案例分析

    [问题] 有台MySQL服务器不定时的会出现并发线程的告警,从记录信息来看,有大量insert的慢查询,执行几十秒,等待flushing log,状态query end [初步分析] 从等待资源来看, ...

  6. 改进动态设置query cache导致额外锁开销的问题分析及解决方法-mysql 5.5 以上版本

    改进动态设置query cache导致额外锁开销的问题分析及解决方法 关键字:dynamic switch for query cache,  lock overhead for query cach ...

  7. MySQL服务器 IO 100%的分析与优化方案

    前言 压力测试过程中,如果因为资源使用瓶颈等问题引发最直接性能问题是业务交易响应时间偏大,TPS逐渐降低等.而问题定位分析通常情况下,最优先排查的是监控服务器资源利用率,例如先用TOP 或者nmon等 ...

  8. 闰秒导致MySQL服务器的CPU sys过高

    今天,有个哥们碰到一个问题,他有一个从库,只要是启动MySQL,CPU使用率就非常高,其中sys占比也比较高,具体可见下图. 注意:他的生产环境是物理机,单个CPU,4个Core. 于是,他抓取了CP ...

  9. mysql 服务器负载过高的解决分析之路

    最近我们有台 mysql 服务器一直报负载过高,不停的收到阿里云的报警短信,让我很抓狂,登陆上服务器,看下一下,慢查询日志 发现有60多万的慢查询日志,一看这个就知道是搜索带来的,一直想把搜索的服务给 ...

随机推荐

  1. Flink 源码解析 —— Flink JobManager 有什么作用?

    JobManager 的作用 https://t.zsxq.com/2VRrbuf 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac ...

  2. 编译Assimp傻瓜教程

    assimp的编译过程和搭建OpenGL环境时glfw的编译基本相同,建议先阅读环境搭建 下载源码 这里使用的是3.3.1版本,Github下载assimp源码 解压完你会得到 接下来我们要编译这些源 ...

  3. 开源音乐下载神器XMusicDownloader更新,支持歌单一键下载,支持无损音乐

    开源音乐下载神器XMusicDownloader更新啦,新增网易.腾讯音乐歌单歌曲.歌手歌曲.专辑歌曲一键下载,同时支持下载flac无损音乐. 功能 V1.0 功能开源工具软件XMusicDownlo ...

  4. laravel为模型中所有查询统一添加WHERE条件

    在使用laravel开发web系统的过程,需要在model处为该模型统一添加一个条件或者多个条件,研究了一个laravel的模型类,发现model中有个方法是构建查询的,方法如下: /** * Reg ...

  5. 高德全链路压测平台TestPG的架构与实践

    导读 2018年十一当天,高德DAU突破一个亿,不断增长的日活带来喜悦的同时,也给支撑高德业务的技术人带来了挑战.如何保障系统的稳定性,如何保证系统能持续的为用户提供可靠的服务?是所有高德技术人面临的 ...

  6. .net core redis的全套操作

    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). Redis支持主从同步.数据可以从主服务器向任意数 ...

  7. CSS动效集锦,视觉魔法的碰撞与融合(一)

    前言 在本文中我讲述了7种CSS的动效,它们也许看起来并不惊艳,但是我认为却足够传达本文的理念:编写一些特殊的CSS样式的时候需要不拘于常理,要用特殊的认识角度看待标签和样式属性,从而用「绕个弯」的方 ...

  8. Java基础之多态和泛型浅析

    Java基础之多态和泛型浅析 一.前言: 楼主看了许多资料后,算是对多态和泛型有了一些浅显的理解,这里做一简单总结 二.什么是多态? 多态(Polymorphism)按字面的意思就是“多种状态”.在面 ...

  9. ASP.NET Core实现对象自动映射-AgileMapper

    我们为什么要在对象之间做映射 处于耦合性或者安全性考虑或者性能考虑我们不希望将Model模型传递给他们,我们会在项目中创建一些DTO(Data transfer object数据传输对象),进行数据的 ...

  10. 利用Spring Boot+zxing,生成二维码还能这么简单

    在网站开发中,经常会遇到要生成二维码的情况,比如要使用微信支付.网页登录等,本文分享一个Spring Boot生成二维码的例子,这里用到了google的zxing工具类. 本文目录 一.二维码简介二. ...