首页 > 代码库 > NUMA对MySQL InnoDB的性能影响

NUMA对MySQL InnoDB的性能影响


http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/


NUMA架构的CPU下,一个CPU有多个核心,那么每个CPU成为一个NODE

关闭这个特性时

一个NODE 使用自己的本地内存,而尽量不去访问其他NODE的内存,除非本地内存满了


Linux 如何处理NUMA架构

1 把处理器分到节点(NODE),现代处理器一般是每个节点一个处理器,一个处理器上多个核


2 为每个节点连接每个处理器的本地内存模块


3 计算节点间的沟通成本(节点距离)


通过numactl --hardware 命令可以看到Linux如何识别NUMA架构层

available: 4 nodes (0-3)

node 0 cpus: 0 1 2 3 4 5 6 7 32 33 34 35 36 37 38 39

node 0 size: 65512 MB

node 0 free: 2146 MB

node 1 cpus: 8 9 10 11 12 13 14 15 40 41 42 43 44 45 46 47

node 1 size: 65536 MB

node 1 free: 96 MB

node 2 cpus: 16 17 18 19 20 21 22 23 48 49 50 51 52 53 54 55

node 2 size: 65536 MB

node 2 free: 32362 MB

node 3 cpus: 24 25 26 27 28 29 30 31 56 57 58 59 60 61 62 63

node 3 size: 65536 MB

node 3 free: 21805 MB

node distances:

node   0   1   2   3 

  0:  10  11  11  11 

  1:  11  10  11  11 

  2:  11  11  10  11 

  3:  11  11  11  10 


内存是平均分配到每个节点的


# Linux 如何处理资源分配

每个进程和线程继承父亲的NUMA策略.这个策略可以基于每个线程修改.

策略定义了一个进程允许被哪个节点甚至那个核心调度.


每个线程最初配分派给最"适合"的节点运行.线程也可以在其他地方运行,但是调度器试图确保现场运行在最优节点


默认情况下,内存的分配被指派到特定的节点上,即这个线程"当前"运行的节点.

在UMA/SMP 架构下,内存是平等对待的,而在NUMA下,分配其他节点的内存意味着cache的延迟和性能的下降


内存一旦分配到一个节点上,就不会移动到另一个节点,不管系统的需求,它会永远呆在那个节点上.


任何进程的NUMA策略可以被修改,通过numactl作为程序的封装,也可以使用 libnuma 编写代码管理NUMA策略.


例如使用numactl作为程序的封装:

 1 使用指定策略分配内存:

     使用"当前"节点,--localalloc参数指定,这是默认的模式

     优先使用一个节点,但也可以使用其他节点,--preferred=node参数

     永远使用一个节点或一组节点, --membind=nodes

     交叉,轮询所有节点 --interleaved=all 或者 --interleaved=nodes

2 程序运行节点的选择

    指定节点(--cpunodebind=nodes) 或者 一个核心或一组核心 (--physcpubind=cpus)


NUMA 对 MySQL 和 InnoDB 的意义


对于InnoDB和大多数数据库服务器(如Oracle),他们在Linux上的工作方式是,巨大的单一进程,带有多线程.

在NUMA架构下,内存被分派到不同的节点上,当你分配了系统50%以上的内存给一个进程,这就不是一个节点内能完成的事情了.


当不同的查询同时运行时,每个处理器都无法优先地去访问一个特定查询需要内存


事实证明这是一个很重要的问题.通过/proc/pid/numa_maps可以看到mysqld分配的所有内存,你会发现一个有趣的现象


如果你查找anon=size的值,


这是其中一行的值

7ecf14000000 default anon=3584 dirty=3584 active=1024 N1=3584


7ecf14000000  虚拟内存地址

default    NUMA 策略

anon=number  匿名页面的数量

dirty  脏页,被修改的页

通常分配给进程的页总是使用的,因此都是脏的,但是由于fork,进程会有很多copy-on-write的页面的映射,他们不是脏的 

swapcache=number 

active  这个列出现,表示多少页面出现在活动列表,同时意味着还有一些不活跃的页面,它们将要被swapper换页出去

N0 and N1 每个节点的页面


通过一个脚本,可以统计出所有内存的情况


perl /data0/script/numa-maps-summary.pl < /proc/4417/numa_maps

N0        :       392133 (  1.50 GB)

N1        :       792466 (  3.02 GB)

N2        :       531028 (  2.03 GB)

N3        :      3743392 ( 14.28 GB)

active    :      4314131 ( 16.46 GB)

anon      :      5457149 ( 20.82 GB)

dirty     :      5456665 ( 20.82 GB)

mapmax    :          268 (  0.00 GB)

mapped    :         1930 (  0.01 GB)

swapcache :          484 (  0.00 GB)


读取/proc/pid/numa_maps的信息会阻塞进程

http://blog.wl0.org/2012/09/checking-procnuma_maps-can-be-dangerous-for-mysql-client-connections/



不但是mysql 还有mangodb

根据官方文档的解释,Linux, NUMA, MongoDB 这三者不是很和谐,如果当前硬件是 NUMA 的,可以把它给关了:

# numactl --interleave=all sudo -u mongodb mongod --port xxx  --logappend --logpath yyy --dbpath zzz

(vm.overcommit_ratio = 100, vm.overcommit_memory = 2) 


vm.zone_reclaim_mode 设置为 0。

系统给 NUMA node 分配内存,如果 NUMA node 已经满了,这时候,系统会为本地的 NUMA node 回收内存而不是将多出来的内存给 remote NUMA node,这样整体的性能会更好,但是在某些情况下,给 remote NUMA node 分配内存会比回收本地的 NUMA node 更好,这时候就需要将 zone_reclaim_mode 给关闭了



numactl --interleave all 




NUMA对MySQL InnoDB的性能影响