MySQL 调优基础(一) CPU与进程

通常而言,MySQL 的调优能够分为两个层面,一个是在MySQL层面上进行的调优,好比SQL改写,索引的添加,MySQL各类参数的配置;另外一个层面是从操做系统的层面和硬件的层面来进行调优。操做系统的层面的调优,通常要先定位到是那种资源出现瓶颈——CPU、 内存、硬盘、网络,而后入手调优。因此其实MySQL 的调优,其实不是那么简单,它要求咱们对 硬件、OS、MySQL 三者都具备比较深刻的理解。好比 NUMA 架构的CPU是如何分配CPU的,以及是如何分配内存的,如何避免致使SWAP的发生;Linux 系统的IO调度算法选择哪种——CFQ、DEADLINE、NOOP、仍是 ANTICIPATORY;MySQL的redo log和undo log它们的写哪一个是顺序写,哪一个是随机写?node

因此其实,若是想要对 MySQL 进行调优,要求咱们必须对 硬件和OS,以及MySQL的内部实现原理,都要有很好的掌握。本文关于MySQL调优基础之 CPU和进程。mysql

1、CPU 架构之 NUMA和SMP

SMP:称为共享内存访问CPU(Shared Memory Mulpti Processors), 也称为对称型CPU架构(Symmetry Multi Processors)ios

NUMA:非统一内存访问 (Non Uniform Memory Access)算法

它们最重要的区别在于内存是否绑定在各个物理CPU上,以及CPU如何访问内存:sql

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,显然访问速度是最快的;app

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中分配内存的目的。

1.1  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 certain signals (for example SIGINT, SIGSTOP) is in this state. The process is waiting to be

     resumed by a signal such as SIGCONT.

3)TASK_INTERRUPTIBLE: In this state, the process is suspended and waits for a certain condition to be satisfied. If a process is in

     TASK_INTERRUPTIBLE state and it receives a signal to stop, the process state is changed and operation will be interrupted. A typical

     example of a TASK_INTERRUPTIBLE process is a process waiting for keyboard interrupt.

4)TASK_UNINTERRUPTIBLE: Similar to TASK_INTERRUPTIBLE. While a process in TASK_INTERRUPTIBLE state can be interrupted, 

     sending a signal does nothing to the process in TASK_UNINTERRUPTIBLE state. A typical example of a TASK_UNINTERRUPTIBLE

     process is a process waiting for disk I/O operation.

5)TASK_ZOMBIE: After a process exits with exit() system call, its parent should know of the termination. In TASK_ZOMBIE state, a

     process is waiting for its parent to be notified to release all the data structure.

除了 TASK_RUNNING 中的进程可能在运行以外,其它状态的进程都没有在运行。可是其实 TASK_UNINTERRUPTIBLE 比较特殊,它其实能够看作是在运行的,由于他是在等待磁盘操做完成,因此其实从系统的角度,而不是从进程的角度而言,其实系统是在为进程运行的。这也就是为何 load average 中的数值,是包括了 TASK_RUNNING 和 TASK_UNINTERRUPTIBLE 两种状态的进程的平均值。

进程如何使用内存

进程的运行,必须申请和使用内存,最重要的包括堆和栈:

进程使用的内存,能够用 pmap, ps 等待命令行来查看。在后面会有站么的内存调优文章介绍。

CPU 调度:

前面介绍了CPU的调度涉及到进程的优先级和nice level. Linux中进程的调度算法是 O(1)的,因此进程数量的多少不会影响进程调度的效率。

进程的调度涉及到两个优先级数组(优先级队列):active, expired 。CPU按照优先级调度 active 队列中的进程,队列中全部进程调度完成以后,交换active队列和expired队列,继续调度。

NUMA架构的CPU在调度时,通常不会垮node节点进行调度,除非一个node节点CPU超载了而且请求进行负载均衡。由于垮node节点CPU调度影响性能。

3、 Linux 如何度量 CPU

1)CPU utilization:最直观最重要的就是CPU的使用率。若是长期超过80%,则代表CPU遇到了瓶颈;

2)User time: 用户进程使用的CPU;该数值越高越好,代表越多的CPU用在了用户实际的工做上

3)System time: 内核使用的CPU,包括了硬中断、软中断使用的CPU;该数值越低越好,过高代表在网络和驱动层遇到瓶颈;

4)Waiting: CPU花在等待IO操做上的时间;该数值很高,代表IO子系统遇到瓶颈;

5)Idel time: CPU空闲的时间;

6)Load average: the average of the sum of TASK_RUNNING and TASK_UNINTERRUPTIBLE processes. If processes that request CPU time are blocked (which means that the CPU has no time to process them), the load average will increase. On the other hand, if each 
process gets immediate access to CPU time and there are no CPU cycles lost, the load will decrease.

7)Context Switch: 上下文切换;

如何检测CPU:

检测CPU使用状况最好的工具是 top 命令:

3.1  top 命令 查看CPU 信息

要调优,那么就必须读懂 不少 命令行工具的输出。上面的top命令包括了不少的信息:

第一行:

top - 14:35:55 up 25 min, 4 users,   load average: 0.10, 0.07, 0.14

分别表示的是:当前系统时间;up 25 min表示已经系统已经运行25分钟; 4 users:表示系统中有4个登陆用户;

load average: 分别表示最近 1 分钟, 5 分钟, 15分钟 CPU的负载的平均值。

(load average: the average of the sum of TASK_RUNNING and TASK_UNINTERRUPTIBLE processes);

这一行最重要的就是 load average

第二行:

Tasks: 92 total,  1 running, 91 sleeping , 0 stopped, 0 zombie

分别表示系统中的进程数:总共92个进程, 1个在运行,91个在sleep,0个stopped, 0个僵尸;

第三行:

Cpu(s): 0.0%us,  1.7 %sy, 0.0%ni, 97.7%id, 0.0%wa, 0.3%hi, 0.3%si, 0.0%st

这一行提供了关于CPU使用率的最重要的信息,分别表示 users time, system time, nice time, idle time, wait time, hard interrupte time, soft interrupted time, steal time; 其中最终要的是:users time, system time, wait time ,idle time 等等。nice time 表示用于调准进程nice level所花的时间。

第四行:

Mem:  total, used ,free, buffers

提供的是关于内存的信息,由于Linux会尽可能的来使用内存来进行缓存,因此这些信息没有多大的价值,free数值小,并不表明存在内存瓶颈;

第五行:

Swap: total, used, free ,cached

提供的是关于swap分区的使用状况,这些信息也没有太大的价值,由于Linux的使用内存的机制决定的。used值很大并不表明存在内存瓶颈;

剩下是关于每一个进程使用的资源的状况,进程的各类信息,按照使用CPU的多少排序,每一个字段的含义以下:

PID: 表示进程ID;USER: 表示运行进程的用户;PR:表示进程优先级;NI:表示进程nice值,默认为0;

VIRT:The  total  amount  of  virtual  memory  used by the task.  It includes all code, data and shared libraries plus pages that have been swapped out. 进程占用的虚拟内存大小,包括了swap out的内存page;

RES: Resident size (kb)。The non-swapped physical memory a task is using. 进程使用的常驻内存大小,没有包括swap out的内存;

SHR:Shared Mem size (kb)。The amount of shared memory used by a task.  It simply reflects memory that could be potentially shared

         with other processes. 其实应该就是使用 shmget() 系统调用分配的共享内存,能够在多个进程之间共享访问。

S: 表示进程处于哪一种状态:R: Running; S: sleeping; T: stoped; D: interrupted; Z:zomobie;

%CPU: 进程占用的CPU;

%MEM:进程占用的内存;

%TIME+: 进程运行时间;

COMMAND: 进程运行命令;

读懂 top 等相关命令行的信息是进行调优的基础。其实这些命令行的输出的含义,在man top中都有是否详细的说明。只要耐心看手册就好了。

上面的 top 命令默认是以 进程为单位来显示的,咱们也能够以线程为单位来显示: top -H

能够看到以线程为单位是,Tasks totol数量明显增长了,有92增长到了 134,由于 mysqld 是线程架构的,后台有多个后台线程。

若是仅仅想查看 CPU 的 load average,使用uptime命令就好了:

[root@localhost ~]# uptime
 15:26:59 up  1:15,  4 users,  load average: 0.00, 0.02, 0.00

3.2  vmstat 查看CPU 信息

上面各个字段的含义:

FIELD DESCRIPTION FOR VM MODE
   Procs
       r: The number of processes waiting for run time.
       b: The number of processes in uninterruptible sleep.
   Memory
       swpd: the amount of virtual memory used.
       free: the amount of idle memory.
       buff: the amount of memory used as buffers.
       cache: the amount of memory used as cache.
       inact: the amount of inactive memory. (-a option)
       active: the amount of active memory. (-a option)
   Swap
       si: Amount of memory swapped in from disk (/s).
       so: Amount of memory swapped to disk (/s).
   IO
       bi: Blocks received from a block device (blocks/s).
       bo: Blocks sent to a block device (blocks/s).
   System
       in: The number of interrupts per second, including the clock.
       cs: The number of context switches per second.
   CPU
       These are percentages of total CPU time.
       us: Time spent running non-kernel code. (user time, including nice time)
       sy: Time spent running kernel code. (system time)
       id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
       wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
       st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.

和CPU相关的信息有 user time, system time, idle time, wait time, steal time;

另外提供了关于中断和上下文切换的信息。System 中的in,表示每秒的中断数,cs表示每秒的上下文切换数;

其它的字段是关于内存和磁盘的。

3.3  iostat 命令查看 CPU 信息

[root@localhost ~]# iostat
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       09/30/2015      _i686_  (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.27    0.02    4.74    0.28    0.00   94.69

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
scd0              0.01         0.08         0.00        536          0
sda               1.64        42.27         8.97     290966      61720
[root@localhost ~]# iostat -c
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       09/30/2015      _i686_  (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.26    0.02    4.72    0.27    0.00   94.72

提供了cpu的平均使用率。

3.4  ps 命令查看某个进程和某个线程的 CPU 信息

好比我想查看 mysqld 的相关信息:

[root@localhost ~]# pidof mysqld
2412
[root@localhost ~]# ps -mp 2412 -o THREAD,pmem,rss,vsz,tid,pid
USER     %CPU PRI SCNT WCHAN  USER SYSTEM %MEM   RSS    VSZ   TID   PID
mysql     6.7   -    - -         -      - 42.8 441212 752744    -  2412
mysql     6.5  19    - -         -      -    -     -      -  2412     -
mysql     0.0  19    - -         -      -    -     -      -  2414     -
mysql     0.0  19    - -         -      -    -     -      -  2415     -
mysql     0.0  19    - -         -      -    -     -      -  2416     -
mysql     0.0  19    - -         -      -    -     -      -  2417     -
mysql     0.0  19    - -         -      -    -     -      -  2418     -
mysql     0.0  19    - -         -      -    -     -      -  2419     -
mysql     0.0  19    - -         -      -    -     -      -  2420     -
mysql     0.0  19    - -         -      -    -     -      -  2421     -
mysql     0.0  19    - -         -      -    -     -      -  2422     -
mysql     0.0  19    - -         -      -    -     -      -  2423     -
mysql     0.0  19    - -         -      -    -     -      -  2425     -
mysql     0.0  19    - -         -      -    -     -      -  2426     -
mysql     0.0  19    - -         -      -    -     -      -  2427     -
mysql     0.0  19    - -         -      -    -     -      -  2428     -
mysql     0.0  19    - -         -      -    -     -      -  2429     -
mysql     0.0  19    - -         -      -    -     -      -  2430     -
mysql     0.0  19    - -         -      -    -     -      -  2431     -
mysql     0.0  19    - -         -      -    -     -      -  2432     -
mysql     0.0  19    - -         -      -    -     -      -  2433     -
mysql     0.0  19    - -         -      -    -     -      -  2434     -

先得到 mysqld 的基础PID 2412,

而后查看其线程的信息:ps -mp 2412-o THREAD,pmem,rss,vsz,tid,pid ( -p 指定进程PID, -o 指定输出格式,参见man ps)

第一列就是关于线程CPU的信息。另外咱们也能够查出是占有的CPU很高的线程的tid。

关于ps咱们通常使用 ps -elf , 若是想查看线程,能够 ps -elLf,其中的L表示 Leight weight process轻量级进程。

3.5  进程分析是终极利器——pidstat 

pidstat是进程分析的终极利器,利用它能够分析进程(包括进程中全部每一个线程)的各类信息:

cpu使用(默认就是cpu, -u 也是cpu),  内存使用(-r 包括page fault),IO状况(-d),进程切换(-w),

pidstat 可使用 -p xxx 指定进程pid,单独分析一个进程及其全部线程;也能够是全部进程 -p ALL,或者是全部活动进程(默认是全部活动进程):

1)默认是全部活动进程的 CPU信息:

[root@localhost ~]# pidstat
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:08:32 AM       PID    %usr %system  %guest    %CPU   CPU  Command
11:08:32 AM         1    0.00    0.11    0.00    0.11     0  init
11:08:32 AM         2    0.00    0.00    0.00    0.00     0  kthreadd
11:08:32 AM         4    0.00    0.01    0.00    0.01     0  ksoftirqd/0
11:08:32 AM         6    0.00    0.02    0.00    0.02     0  watchdog/0
11:08:32 AM         7    0.00    0.09    0.00    0.09     0  events/0

2)全部进程包括非活动进程,默认是CPU信息:

[root@localhost ~]# pidstat -p ALL
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:09:48 AM       PID    %usr %system  %guest    %CPU   CPU  Command
11:09:48 AM         1    0.00    0.10    0.00    0.10     0  init
11:09:48 AM         2    0.00    0.00    0.00    0.00     0  kthreadd
11:09:48 AM         3    0.00    0.00    0.00    0.00     0  migration/0
11:09:48 AM         4    0.00    0.01    0.00    0.01     0  ksoftirqd/0
11:09:48 AM         5    0.00    0.00    0.00    0.00     0  stopper/0
[root@localhost ~]# pidstat -p ALL | wc -l
83
[root@localhost ~]# ps -elf| wc -l
81

能够看到 上面两个结果统计系统全部进程数目是一致的。差了2,是由于结果头信息不一样致使的。

3)查看 IO 信息(分别以进程角度和线程角度):

进程角度:

[root@localhost ~]# pidof mysqld
1386
[root@localhost ~]# pidstat -p 1386 -d 1 2
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:13:25 AM       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
11:13:26 AM      1386      0.00      0.00      0.00  mysqld
11:13:27 AM      1386      0.00      0.00      0.00  mysqld
Average:         1386      0.00      0.00      0.00  mysqld

线程角度:

[root@localhost ~]# pidstat -p 1386 -d -t 1 2
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:13:35 AM      TGID       TID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
11:13:36 AM      1386         -      0.00      0.00      0.00  mysqld
11:13:36 AM         -      1386      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1388      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1389      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1390      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1391      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1392      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1393      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1394      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1395      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1396      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1397      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1399      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1400      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1401      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1402      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1403      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1404      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1405      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1406      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1407      0.00      0.00      0.00  |__mysqld
11:13:36 AM         -      1408      0.00      0.00      0.00  |__mysqld

4)查看 内存 信息(分别以进程角度和线程角度):

[root@localhost ~]# pidof mysqld
1386
[root@localhost ~]# pidstat -p 1386 -r 1 2
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:15:24 AM       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
11:15:25 AM      1386      0.00      0.00  650136 434672  42.18  mysqld
11:15:26 AM      1386      0.00      0.00  650136 434672  42.18  mysqld
Average:         1386      0.00      0.00  650136 434672  42.18  mysqld
[root@localhost ~]# pidstat -p 1386 -r -t 1 2
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:15:30 AM      TGID       TID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
11:15:31 AM      1386         -      0.00      0.00  650136 434672  42.18  mysqld
11:15:31 AM         -      1386      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1388      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1389      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1390      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1391      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1392      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1393      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1394      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1395      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1396      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1397      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1399      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1400      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1401      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1402      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1403      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1404      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1405      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1406      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1407      0.00      0.00  650136 434672  42.18  |__mysqld
11:15:31 AM         -      1408      0.00      0.00  650136 434672  42.18  |__mysqld

5)查看 进程切换 信息(分别以进程角度和线程角度):

[root@localhost ~]# pidstat -p 1386 -w 1 2
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:17:20 AM       PID   cswch/s nvcswch/s  Command
11:17:21 AM      1386      0.00      0.00  mysqld
11:17:22 AM      1386      0.00      0.00  mysqld
Average:         1386      0.00      0.00  mysqld
[root@localhost ~]# pidstat -p 1386 -w -t 1 2
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:17:25 AM      TGID       TID   cswch/s nvcswch/s  Command
11:17:26 AM      1386         -      0.00      0.00  mysqld
11:17:26 AM         -      1386      0.00      0.00  |__mysqld
11:17:26 AM         -      1388      1.98      0.00  |__mysqld
11:17:26 AM         -      1389      1.98      0.00  |__mysqld
11:17:26 AM         -      1390      1.98      0.00  |__mysqld
11:17:26 AM         -      1391      1.98      0.00  |__mysqld
11:17:26 AM         -      1392      1.98      0.00  |__mysqld
11:17:26 AM         -      1393      1.98      0.00  |__mysqld
11:17:26 AM         -      1394      1.98      0.00  |__mysqld
11:17:26 AM         -      1395      1.98      0.00  |__mysqld
11:17:26 AM         -      1396      1.98      0.00  |__mysqld
11:17:26 AM         -      1397      1.98      0.00  |__mysqld
11:17:26 AM         -      1399      0.99      0.00  |__mysqld
11:17:26 AM         -      1400      0.99      0.00  |__mysqld
11:17:26 AM         -      1401      0.00      0.00  |__mysqld
11:17:26 AM         -      1402      0.99      0.00  |__mysqld
11:17:26 AM         -      1403      0.00      0.00  |__mysqld
11:17:26 AM         -      1404      0.99      0.00  |__mysqld
11:17:26 AM         -      1405      0.00      0.00  |__mysqld
11:17:26 AM         -      1406      0.00      0.00  |__mysqld
11:17:26 AM         -      1407      0.00      0.00  |__mysqld
11:17:26 AM         -      1408      0.00      0.00  |__mysqld

6)同时,咱们也能够将线程 tid 做为一个进程的 pid 来进行分析,由于本质上,线程是特殊的进程,可是他仍是进程:

先查一个进程的全部线程

[root@localhost ~]# pidof mysqld
1386
[root@localhost ~]# pidstat -p 1386 -t
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:19:55 AM      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
11:19:55 AM      1386         -    0.06    0.53    0.00    0.58     0  mysqld
11:19:55 AM         -      1386    0.03    0.16    0.00    0.19     0  |__mysqld
11:19:55 AM         -      1388    0.00    0.03    0.00    0.03     0  |__mysqld
11:19:55 AM         -      1389    0.00    0.04    0.00    0.04     0  |__mysqld
11:19:55 AM         -      1390    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1391    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1392    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1393    0.00    0.02    0.00    0.03     0  |__mysqld
11:19:55 AM         -      1394    0.00    0.04    0.00    0.04     0  |__mysqld
11:19:55 AM         -      1395    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1396    0.00    0.03    0.00    0.03     0  |__mysqld
11:19:55 AM         -      1397    0.00    0.03    0.00    0.03     0  |__mysqld
11:19:55 AM         -      1399    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1400    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1401    0.00    0.00    0.00    0.00     0  |__mysqld
11:19:55 AM         -      1402    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1403    0.00    0.00    0.00    0.00     0  |__mysqld
11:19:55 AM         -      1404    0.00    0.02    0.00    0.02     0  |__mysqld
11:19:55 AM         -      1405    0.00    0.00    0.00    0.00     0  |__mysqld
11:19:55 AM         -      1406    0.00    0.00    0.00    0.00     0  |__mysqld
11:19:55 AM         -      1407    0.00    0.00    0.00    0.00     0  |__mysqld
11:19:55 AM         -      1408    0.00    0.00    0.00    0.00     0  |__mysqld

而后将她的线程 tid=1408 做为一个进程(pid)来分析:

[root@localhost ~]# pidstat -p 1408
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

11:21:26 AM       PID    %usr %system  %guest    %CPU   CPU  Command
11:21:26 AM      1408    0.06    0.52    0.00    0.58     0  mysqld

3.6  mpstat(multi processor stat) 命令查看多核CPU中每一个CPU核心的信息

[root@localhost ~]# mpstat
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       09/30/2015      _i686_  (1 CPU)

04:11:50 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest   %idle
04:11:50 PM  all    0.26    0.02    4.30    0.27    0.26    0.15    0.00    0.00   94.74

这里由于虚拟机中的单核CPU,因此只显示all,没有显示其它核心的CPU使用状况。

3.7  sar -P {n, ALL}, 查看某个CPU或者全部CPU基本信息,sar -q 查看cpu队列,任务队列,以及负载:

[root@localhost ~]# sar -P 0
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

10:19:38 AM       LINUX RESTART

10:30:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
10:40:02 AM       0      0.12      0.00      0.67      0.00      0.00     99.21
10:50:01 AM       0      0.02      0.00      0.49      0.01      0.00     99.49
11:00:01 AM       0      0.02      0.00      0.64      0.00      0.00     99.34
11:10:02 AM       0      0.03      0.00      0.49      0.02      0.00     99.46
11:20:01 AM       0      0.08      0.00      1.65      0.00      0.00     98.27
11:30:01 AM       0      0.14      0.00      1.36      0.05      0.00     98.44
Average:          0      0.07      0.00      0.88      0.01      0.00     99.04
[root@localhost ~]# sar -P ALL
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

10:19:38 AM       LINUX RESTART

10:30:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
10:40:02 AM     all      0.12      0.00      0.67      0.00      0.00     99.21
10:40:02 AM       0      0.12      0.00      0.67      0.00      0.00     99.21

sar -P 0 表示 0 号CPU, sar -P ALL 表示全部CPU。

[root@localhost ~]# sar -q
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/15/2015      _i686_  (1 CPU)

10:19:38 AM       LINUX RESTART

10:30:01 AM   runq-sz  plist-sz   ldavg-1   ldavg-5  ldavg-15
10:40:02 AM         0       102      0.00      0.01      0.06
10:50:01 AM         0       101      0.00      0.00      0.01
11:00:01 AM         0       101      0.00      0.00      0.00
11:10:02 AM         0       102      0.07      0.02      0.00
11:20:01 AM         0       102      0.00      0.00      0.00
11:30:01 AM         0       106      0.05      0.01      0.00
Average:            0       102      0.02      0.01      0.01

runq-sz: Run queue length (number of tasks waiting for run time). cpu上等待执行的任务队列
plist-sz: Number of tasks in the task list. 系统中的任务/进程队列

ldavg-1 ldavg-5 ldavg-15 就是 uptime 命令中的值含义同样,过去1分钟,5分钟,15分钟的平均负载。

上面的 plist-ze = 102, 咱们查看一下系统中的进程(线程)的数量:

[root@localhost ~]# ps -elf | wc -l
84
[root@localhost ~]# ps -elLf | wc -l
107

102 和 107-1 仍是比较接近的。

4、CPU 相关调优

1)使用上面介绍的工具:top, vmstat, iostat, ps -mp xxx -o, mpstat 等,能够确认是否存在 CPU 瓶颈。而后确认 user time, system time, wait time, context switch......那种占用比例高,确认是哪一个进程占用CPU高。若是能确认是 mysqld 的相关进程,那么就能够从 mysql 上入手进行调优。好比使用mysql的命令 show processlist ;查看是哪一个sql致使的,找到sql以后,进行优化或者重写等等,或者将其放到slave上去运行。

2)若是是 非必须的进程占用CPU,那么能够杀掉,而后使用cron让其在非高峰期去执行;或者使用 renice 命令下降其优先级;

[root@localhost ~]# renice -n -10 -p 2041
2041: old priority 10, new priority -10

将进程 2041 的优先级设置为 -10.

3)能够跟踪进程,查找缘由:strace -aef -p spid -o file

[root@localhost ~]# strace -aef -p 2041 -o mysql.txt
Process 2041 attached - interrupt to quit
^CProcess 2041 detached
[root@localhost ~]# ll mysql.txt
-rw-r--r-- 1 root root 10091 Sep 30 16:44 mysql.txt
[root@localhost ~]# head mysql.txt
read(0, "\33", 1) = 1
read(0, "[", 1) = 1
read(0, "A", 1) = 1
write(1, "select version();", 17) = 17
read(0, "\n", 1) = 1
write(1, "\n", 1) = 1
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT TERM CONT TSTP WINCH], [], 8) = 0
rt_sigaction(SIGINT, {0x8053ac0, [INT], SA_RESTART}, NULL, 8) = 0
rt_sigaction(SIGTSTP, {SIG_DFL, [], 0}, NULL, 8) = 0

4)换更好的CPU。

相关文章
相关标签/搜索