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。

相關文章
相關標籤/搜索