数据库内核月报 - 2015 / 07-MySQL · 社区动态 · MySQL内存分配支持NUMA

NUMA 问题曾经一直是困扰DBA的一个大问题,早在 2010 年, 就有人给MySQL报了Bug#57241, 指出了MySQL在x86系统下存在严重的 “swap insanity” 问题。在NUMA架构越来越普遍的今天,这个问题越来越严重。

MySQL的 swap insanity 问题

有同学专门翻译了Jeremy Cole关于 “swap insanity” 问题的文章,原文看这里

如果你没空看的话,这里简单描述一下,就是当你把主机大部分内存分配给InnoDB时,你会发现明明操作系统还有很多内存,但是却有很多内存被交换到了SWAP分区。

这里可以下载到一个测试的C代码,如果你有NUMA架构的服务器,可以测试下不同分配方式的性能差异:

sudo -s
echo 2048 > /proc/sys/vm/nr_hugepages
echo 1000000000000 > /proc/sys/kernel/shmmax

# Node local allocation
for i in `seq 0 4 127`
do
./latency2001 -a $i -c $i -l 128M
done

# Allocate on memory on CPU 0
for i in `seq 0 4 127`
do
./latency2001 -a 0 -c $i -l 128M
done

有两个方式可以解决这个问题:
1. 在Linux Kernel启动参数中加上numa=off(这样也会影响到其他进程使用NUMA);
2. 在mysqld_safe脚本中加上“numactl –interleave all”来启动mysqld。

当然如果跑多实例,我也用过直接绑定mysqld进程到某个numa节点的方式,不过这要求每个实例分配的内存不超过每个NUMA节点管理的内存。脚本可以看这里

5年过去了,官方依然没有解决这个Bug。但好消息是,官方终于着手解决这个问题了,Stewart Smith 同学提交的Bug#72811,其Patch即将出现在MySQL 5.6.27, 5.7.9 版本之中。

代码层面解决NUMA问题

如果在代码层面彻底解决NUMA问题,那么我们需要解决两个问题:
1. 全局内存应该采用interleave的分配方式分散在不同的numa node上;
2. 线程内存应该采用local的分配方式分配在线程运行的numa node上。

Linux 提供了 set_mempolicy() 函数可以用来设置进程的内存分配策略,其中默认的MPOL_DEFAULT策略就是在当前运行的节点上分配内存,而MPOL_INTERLEAVE策略则是跨所有节点来分配内存。这个函数的说明可以看这里

因此对于MySQL Server和InnoDB引擎都需要做修改:
1. 在mysqld_main()入口设置 set_mempolicy(MPOL_INTERLEAVE, NULL, 0) 启用全局分配方式;
2. 在MySQL启动完成之后设置set_mempolicy(MPOL_DEFAULT, NULL, 0) 启用本地分配方式;
3. 在InnoDB入口时设置 set_mempolicy(MPOL_INTERLEAVE, NULL, 0) 启用全局分配方式;
4. 在Buffer Pool分配完成时设置 set_mempolicy(MPOL_DEFAULT, NULL, 0) 启用本地分配方式。

MySQL 5.6.27, 5.7.9 发布之后,将会增加一个 innodb_numa_interleave 参数来控制这个策略。innodb_numa_interleave 如果打开,那么将会按上面的策略来设置内存分配方式,如果关闭或者主机不支持NUMA,那么还是按原来的方式分配。

我们一起期待新版本的发布吧,妈妈再也不用担心我的NUMA了!

时间: 2024-11-01 01:48:12

数据库内核月报 - 2015 / 07-MySQL · 社区动态 · MySQL内存分配支持NUMA的相关文章

MySQL内核月报 2015.01-MySQL · 捉虫动态· mysql client crash一例

背景 客户使用mysqldump导出一张表,然后使用mysql -e 'source test.dmp'的过程中client进程crash,爆出内存的segment fault错误,导致无法导入数据. 问题定位 test.dmp文件大概50G左右,查看了一下文件的前几行内容,发现: 问题定位到第一行出现了不正常warning的信息,是由于客户使用mysqldump命令的时候,重定向了stderr.即: mysqldump ...>/test.dmp 2>&1 导致error或者warn

MySQL内核月报 2015.01-MySQL · 捉虫动态· InnoDB自增列重复值问题

问题重现 先从问题入手,重现下这个bug 这里我们关闭mysql,再启动mysql,然后再插入一条数据 我们看到插入了(2,2),而如果我没有重启,插入同样数据我们得到的应该是(4,2). 上面的测试反映了mysqld重启后,InnoDB存储引擎的表自增id可能出现重复利用的情况. 自增id重复利用在某些场景下会出现问题.依然用上面的例子,假设t1有个历史表t1_history用来存t1表的历史数据,那么mysqld重启前,ti_history中可能已经有了(2,2)这条数据,而重启后我们又插入

MySQL内核月报 2015.03-MySQL · 捉虫动态· pid file丢失问题分析

现象 mysql5.5,通过命令show variables like '%pid_file%'; 可以查到pid文件位置,例如/home/mysql/xx.pid.但发现在此目录下找不到此pid文件. 背景知识 mysql pid文件记录的是当前mysqld进程的pid. 通过mysqld_safe启动mysqld时,mysqld_safe会检查PID文件,未指定PID文件时,pid文件默认名为$DATADIR/`hostname`.pid pid文件不存在,不做处理 文件存在,且pid已占用

MySQL内核月报 2015.01-MySQL · 捉虫动态· 设置 gtid_purged 破坏AUTO_POSITION复制协议

bug描述 Oracle 最新发布的版本 5.6.22 中有这样一个关于GTID的bugfix,在主备场景下,如果我们在主库上 SET GLOBAL GTID_PURGED = "some_gtid_set",并且 some_gtid_set 中包含了备库还没复制的事务,这个时候如果备库接上主库的话,预期结果是主库返回错误,IO线程挂掉的,但是实际上,在这种场景下主库并不报错,只是默默的把自己 binlog 中包含的gtid事务发给备库.这个bug的造成的结果是看起来复制正常,没有错误

MySQL内核月报 2015.01-MySQL · 捉虫动态· replicate filter 和 GTID 一起使用的问题

问题描述 当单个 MySQL 实例的数据增长到很多的时候,就会考虑通过库或者表级别的拆分,把当前实例的数据分散到多个实例上去,假设原实例为A,想把其中的5个库(db1/db2/db3/db4/db5)拆分到5个实例(B1/B2/B3/B4/B5)上去. 拆分过程一般会这样做,先把A的相应库的数据导出,然后导入到对应的B实例上,但是在这个导出导入过程中,A库的数据还是在持续更新的,所以还需在导入完后,在所有的B实例和A实例间建立复制关系,拉取缺失的数据,在业务不繁忙的时候将业务切换到各个B实例.

MySQL内核月报 2015.02-MySQL · 捉虫动态· 变量修改导致binlog错误

背景 MySQL 5.6.6 版本新加了这样一个参数--log_bin_use_v1_row_events,这个参数用来控制binlog中Rows_log_event的格式,如果这个值为1的话,就用v1版的Rows_log_event格式(即5.6.6之前的),默认是0,用新的v2版本的格式,更详细看官方文档.这个参数一般保持默认即可,但是当我们需要搭 5.6->5.5 这要的主备的时候,就需要把主库的这个值改为1,不然5.5的备库不能正确解析Rows_log_event.最近在使用这个参数的时

阿里数据库内核月报:2015年07月

# 01 MySQL · 引擎特性 · Innodb change buffer介绍 # 02 MySQL · TokuDB · TokuDB Checkpoint机制 # 03 PgSQL · 特性分析 · 时间线解析 # 04 PgSQL · 功能分析 · PostGIS 在 O2O应用中的优势 # 05 MySQL · 引擎特性 · InnoDB index lock前世今生 # 06 MySQL · 社区动态 · MySQL内存分配支持NUMA # 07 MySQL · 答疑解惑 · 外

阿里数据库内核月报:2015年06月

# 01 MySQL · 引擎特性 · InnoDB 崩溃恢复过程 # 02 MySQL · 捉虫动态 · 唯一键约束失效 # 03 MySQL · 捉虫动态 · ALTER IGNORE TABLE导致主备不一致 # 04 MySQL · 答疑解惑 · MySQL Sort 分页 # 05 MySQL · 答疑解惑 · binlog event 中的 error code # 06 PgSQL · 功能分析 · Listen/Notify 功能 # 07 MySQL · 捉虫动态 · 任性的 

阿里数据库内核月报:2015年08月

# 01 MySQL · 社区动态 · InnoDB Page Compression # 02 PgSQL · 答疑解惑 · RDS中的PostgreSQL备库延迟原因分析 # 03 MySQL · 社区动态 · MySQL5.6.26 Release Note解读 # 04 PgSQL · 捉虫动态 · 执行大SQL语句提示无效的内存申请大小 # 05 MySQL · 社区动态 · MariaDB InnoDB表空间碎片整理 # 06 PgSQL · 答疑解惑 · 归档进程cp命令的core