一般而言,MySQL 的调优可以分为两个层面,一个是在MySQL层面上进行的调优,比如SQL改写,索引的添加,MySQL各种参数的配置;另一个层面是从操作系统的层面和硬件的层面来进行调优。操作系统的层面的调优,一般要先定位到是那种资源出现瓶颈——CPU、 内存、硬盘、网络,然后入手调优。所以其实MySQL 的调优,其实不是那么简单,它要求我们对 硬件、OS、MySQL 三者都具有比较深入的理解。比如 NUMA 架构的CPU是如何分配CPU的,以及是如何分配内存的,如何避免导致SWAP的发生;Linux 系统的IO调度算法选择哪一种——CFQ、DEADLINE、NOOP、还是 ANTICIPATORY;MySQL的redo log和undo log它们的写哪个是顺序写,哪个是随机写?
?
所以其实,如果想要对 MySQL 进行调优,要求我们必须对 硬件和OS,以及MySQL的内部实现原理,都要有很好的掌握。本文关于MySQL调优基础之 CPU和进程。
?
1. CPU 架构之 NUMA和SMP
?
SMP:称为共享内存访问CPU(Shared Memory Mulpti Processors), 也称为对称型CPU架构(Symmetry Multi Processors)
?
NUMA:非统一内存访问 (Non Uniform Memory Access)
?
它们最重要的区别在于内存是否绑定在各个物理CPU上,以及CPU如何访问内存:
?
SMP架构的CPU内部没有绑定内存,所有的CPU争用一个总线来访问所有共享的内存,优点是资源共享,而缺点是总线争用激烈。随着PC服务 器上的CPU数量变多(不仅仅是CPU核数),总线争用的弊端慢慢越来越明显,于是Intel在Nehalem CPU上推出了NUMA架构,而AMD也推出了基于相同架构的Opteron CPU。
?
NUMA 最大的特点是引入了node和distance的概念,node内部有多个CPU,以及绑定的内存。每个node的CPU和内存一般是相等。distance这个概念是用来定义各个node之间调用资源的开销。NUMA架构中内存和CPU的关系如下图所示:
?(node内部有多个CPU,node内部有内存;每两个node之间有 inter-connect)
?
NUMA架构的提出是为了适应多CPU,可以看到node内部的CPU对内存的访问分成了两种情况:
?
1)对node内部的内存的访问,一般称为 local access,显然访问速度是最快的;
?
2)对其它node中的内存的访问,一般称为 remote access,因为要通过 inter-connect,所以访问速度会慢一些;
?
因为CPU和内存是绑定而形成一个node,那么就涉及到CPU如何分配,内存如何分配的问题:
?
1)NUMA的CPU分配策略有cpunodebind、physcpubind。cpunodebind规定进程运行在某几个node之上,而physcpubind可以更加精细地规定运行在哪些核上。
2)NUMA的内存分配策略有localalloc、preferred、membind、interleave。localalloc规定进程从当前 node上请求分配内存;而preferred比较宽松地指定了一个推荐的node来获取内存,如果被推荐的node上没有足够内存,进程可以尝试别的 node。membind可以指定若干个node,进程只能从这些指定的node上请求分配内存。interleave规定进程从所有node上以RR算法交织地请求分配内存,达到随机均匀的从各个node中分配内存的目的。
?
NUMA 架构导致的问题——SWAP
?
因为NUMA架构的CPU,默认采用的是localalloc的内存分配策略,运行在本node内部CPU上的进程,会从本node内部的内存上分配内存,如果内存不足,则会导致swap的产生,严重影响性能!它不会向其它node申请内存。这是他最大的问题。
?
所以为了避免SWAP的产生,一定要将NUMA架构CPU的内存分配策略设置为:interleave; 这样设置的话,任何进程的内存分配,都会随机向各个node申请,虽然remote access会导致一点点的性能损失,但是他杜绝了SWAP导致的严重的性能损失。所以 interleave 其实是将NUMA架构的各个node中的内存,又重新虚拟成了一个共享的内存,但是和SMP不同的是,因为每两个node之间有 inter-connect ,所以又避免了SMP架构总线争用的缺陷。
?
2. CPU 和 Linux 进程
?
进程应该是Linux中最重要的一个概念。进程运行在CPU上,是所有硬件资源分配的对象。Linux中用一个task_struct的结构来描述进程,描述了进程的各种信息、属性、资源。
?
Linux中进程的生命周期和它们涉及的调用:
?
1)父进程调用fork() 产生一个新的自进程;
?
2)子进程调用exec() 指定自己要执行的代码;
?
3)子进程调用exit() 退出,进入zombie状态;
?
4)父进程调用wait(),等待子进程的返回,回收其所有资源;
?
Thread:
?
是一个执行单元,同一进程中所有线程,共享进程的资源。线程一般称为 LWP(Light Weight Process)轻量级进程。所以期限线程没有那么神秘,我们可以将其当做特殊的进程来看待。
?
进程的优先级和nice:
?
进程的调度,涉及到进程的优先级。优先级使用nice level来表示,其值范围:19 ~ -20。值越小,优先级越大,默认为0.
?
一般如果我们想降低某个线程被调度的频率,就可以调高它的nice值(越nice,就越不会去争用CPU)。
?
进程的 context switch:
?
进程上下文切换,是一个极为重要的概念,因为他对性能影响极大。进程的调度,级涉及到进程上下文的切换。上下文切换,是指将进程的所有的信息,从CPU的register中flush到内存中,然后换上其它进程的上下文。频繁的上下文切换,将极大的影响性能。
?
CPU中断处理:
?
CPU的中断处理是优先级最高的任务之一。中断分为:hard interrupte 和 soft interrupt.
?
因为中断发生,就会去运行中断处理程序,也就导致了context switch,所以过多的中断也会导致性能的下降。
?
进程的各种状态 state:
?
进程的各种状态,一定要搞清楚他们的含义,不然后面进程的 load average(top命令和uptime命令)等各种信息会看不懂。
?
1)TASK_RUNNING: In this state, a process is running on a CPU or waiting to run in the queue (run queue).
?
2)TASK_STOPPED: A process suspended by cer