MySQL 調優基礎(四) Linux 磁盤IO

1、IO處理過程

磁盤IO常常會成爲系統的一個瓶頸,特別是對於運行數據庫的系統而言。數據從磁盤讀取到內存,在到CPU緩存和寄存器,而後進行處理,最後寫回磁盤,中間要通過不少的過程,下圖是一個以write爲例的 Linux 磁盤IO子系統的架構:前端

能夠看到IO操做分紅了四個層面:mysql

1)文件系統緩存:處理數據必須先從磁盤讀到緩存,而後修改,而後刷會磁盤。緩存的刷新涉及到兩個參數:vm.dirty_background_ratio、vm.dirty_ratio。還有刷新寫回時,使用到 bio 結構,bio的組成是由磁盤上相鄰的block組成的,因此這裏進行了優化。ios

2)block layer:該層就涉及到 IO調度算法,IO調度算法在mysql服務器是一個很重要的調優手段。系統中全部進程申請的IO操做,所有在這裏進行排隊,等待調度,而後寫回磁盤。調度算法有四種:redis

1> Anticipatory: 適用於我的PC,單磁盤系統;算法

2> CFQ(Complete Fair Queuing):默認的IO調度算法,徹底公平的排隊調度算法。每個進程的IO請求會安排進一個專門的IO隊列,而後按照進程組來公平的調度IO,也就是每個進程組之間按照公平的方式來調度IO。顯然他適合多用戶的系統,可是極爲不適合做爲數據庫系統的IO調度算法,由於顯而易見,數據庫系統中,數據庫進程確定是IO最多的一個進程組,而後它卻只能得到和其它進程同樣多的IO調度機會。因此顯然這是極爲不合理的。數據庫系統絕對不要使用該調度算法sql

3> Deadline: 按照截止期限來循環在各個IO隊列中進行調度,因此它提供了一個近實時的IO系統,而且磁盤throughput也很好,也不會形成starvation.通常mysql系統建議採用該調度算法。數據庫

4> NOOP: 簡單的FIFO隊列進行調度,No operation的意思是,它沒有進行額外的將臨近的IO進行合併的操做,因此它對CPU的使用極少。該調度算法特別適合於SSD。由於SSD在對待順序IO和隨機IO沒有什麼區別。因此它不須要對臨近的IO進行合併。避免了合併操做對CPU的使用。緩存

因此通常而言,對於mysql的系統,若是是SSD,那麼應該使用NOOP調度算法,若是是磁盤,就應該使用Deadline調度算法服務器

查看與修改IO調度算法架構

臨時修改

[root@localhost ~]# cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
[root@localhost ~]# echo noop >  /sys/block/sda/queue/scheduler
[root@localhost ~]# cat /sys/block/sda/queue/scheduler
[noop] anticipatory deadline cfq

永久修改

# vi /boot/grub/menu.lst
更改到以下內容:
kernel /boot/vmlinuz-2.6.18-8.el5 ro root=LABEL=/ elevator=deadline rhgb quiet

重啓以後,查看調度方法:
# cat /sys/block/sda/queue/scheduler 
noop anticipatory [deadline] cfq 
已是deadline了

3)磁盤驅動層:對於順序讀系統而言,很容易在磁盤接口層的帶寬上成爲瓶頸所在;

4)磁盤:對於隨機讀多的系統而言,磁盤很容易成爲瓶頸所在,通常的優化就是使用RAID或者換SSD;

2、IO瓶頸檢測

2.1  使用 iostat 查看磁盤IO

顯示單位問題:默認iostat是以磁盤的block爲單位,也可使用 -k 來指定以 kilobytes 爲單位,或者使用 -m 指定 megabytes 爲單位;

統計開始時間問題:默認iostat和vmstat類似,默認第一次/行都是從開機到目前的一個數據,可使用 -y 選項去掉第一次/行的數據;

CPU與磁盤: iostat 默認會顯示cpu和磁盤的數據,若是隻要cpu數據可使用 -c 選項,若是隻須要磁盤數據,可使用 -d 選項;

時間間隔和重複次數:[interval [times]] 表示磁盤統計數據的間隔時間和次數;

-x : 該選項顯示具體的擴展信息;

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

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.60    0.00    7.80    0.31    0.00   91.30

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
scd0              0.02         0.21         0.00        536          0
sda               2.00        78.60         8.43     198702      21312[root@localhost ~]# iostat -c
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/09/2015      _i686_  (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.48    0.00    6.51    0.25    0.00   92.76
[root@localhost ~]# iostat -d -k
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/09/2015      _i686_  (1 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
scd0              0.02         0.08         0.00        268          0
sda               1.69        31.17         4.15      99363      13224

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

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn
scd0              0.02         0.00         0.00          0          0
sda               1.69         0.03         0.00         97         12

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

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.02     0.00    0.02    0.00     0.00     0.00    10.94     0.00    4.96   4.88   0.01
sda               1.22     0.48    1.13    0.56     0.03     0.00    41.66     0.01    6.83   5.27   0.89

[root@localhost ~]# iostat -d -m -x 2 3
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/09/2015      _i686_  (1 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.02     0.00    0.01    0.00     0.00     0.00    10.94     0.00    4.96   4.88   0.01
sda               1.19     0.48    1.10    0.55     0.03     0.00    41.52     0.01    6.81   5.25   0.87

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda               0.00     0.00    0.00    0.51     0.00     0.00     8.00     0.00    3.00   3.00   0.15

[root@localhost ~]# iostat -y -d -m -x 2 3
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/09/2015      _i686_  (1 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

字段含義:

Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn 分別表示:每秒讀取block的個數,每秒寫block的個數,總共讀了多少個block,總共寫了多少個block

tps: Indicate the number of transfers per second that were issued to the device. A transfer is an I/O request to the device. Multiple logical requests can be combined into a single I/O request to the device. A transfer is of indeterminate size.(就是對磁盤每秒請求多少次IO操做)

rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util

rrqm/s wrqm/s 表示的磁盤讀和寫時每秒發生多少次相鄰磁盤的merge操做;rrqm: read request merge; wrqm:write request merge

r/s w/s 表示每秒讀的次數,寫的次數;

rMB/s wMB/s 表示每秒讀多少MB,寫多少MB

avgrq-sz:The average size (in sectors) of the requests that were issued to the device. 平均一個IO請求涉及到多少個sector

avgqu-sz:The average queue length of the requests that were issued to the device. IO隊列的平均長度,該數值很重要

await:The average time (in milliseconds) for I/O requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.平均每個IO花費了多少毫秒(包括在IO隊列中的排隊時間和讀寫操做花費的時間)。這裏能夠理解爲IO的響應時間,通常地系統IO響應時間應該低於5ms,若是大於10ms就比較大了。

svctm:棄用

%util :Percentage of CPU time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100%. 在統計時間內全部處理IO時間,除以總共統計時間。例如,若是統計間隔1秒,該設備有0.8秒在處理IO,而0.2秒閒置,那麼該設備 的%util = 0.8/1 = 80%,因此該參數暗示了設備的繁忙程度。通常地,若是該參數是100%表示設備已經接近滿負荷運行了(固然若是是多磁盤,即便%util是100%,因 爲磁盤的併發能力,因此磁盤使用未必就到了瓶頸)。

CPU的 %iowait io等待很高;

磁盤的 avgqu-sz數值很大;await數值很高;%util數值很高;均可能預示着磁盤存在瓶頸或者磁盤出現問題或者故障。

2.2  使用 iostat 查看磁盤每一個分區的IO

上面查看的都是整個磁盤的IO狀況,下面的命令能夠查看具體某個磁盤的全部分區的IO狀況:

[root@localhost ~]# iostat -x -d -m -p sda 2 3
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/09/2015      _i686_  (1 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.82     0.43    0.76    0.52     0.02     0.00    38.49     0.01    6.27   4.82   0.62
sda1              0.80     0.42    0.53    0.51     0.02     0.00    45.09     0.01    6.92   5.50   0.57
sda2              0.01     0.02    0.12    0.01     0.00     0.00     9.70     0.00    2.95   2.79   0.04
sda3              0.01     0.00    0.07    0.00     0.00     0.00     8.67     0.00    3.72   3.65   0.03

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda3              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda3              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

[root@localhost ~]# iostat -d -m -p sda 2 3
Linux 2.6.32-504.el6.i686 (localhost.localdomain)       10/09/2015      _i686_  (1 CPU)

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn
sda               1.25         0.02         0.00         97         18
sda1              1.02         0.02         0.00         92         17
sda2              0.13         0.00         0.00          2          0
sda3              0.07         0.00         0.00          1          0

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn
sda               0.00         0.00         0.00          0          0
sda1              0.00         0.00         0.00          0          0
sda2              0.00         0.00         0.00          0          0
sda3              0.00         0.00         0.00          0          0

Device:            tps    MB_read/s    MB_wrtn/s    MB_read    MB_wrtn
sda               0.00         0.00         0.00          0          0
sda1              0.00         0.00         0.00          0          0
sda2              0.00         0.00         0.00          0          0
sda3              0.00         0.00         0.00          0          0

2.3  使用 vmstat 查看磁盤IO

[root@localhost ~]# vmstat 2 4
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 454900  21808  76776    0    0    20     4   97   81  0  5 95  0  0
 0  0      0 454892  21808  76772    0    0     0     8   83  106  0  3 97  0  0
 1  0      0 454760  21816  76772    0    0     0    44  101  153  1  5 94  0  0
 0  0      0 454760  21816  76784    0    0     0     0   57   68  0  1 99  0  0

bi: Blocks received from a block device (blocks/s). 每秒讀取多少個block到內存
 bo: Blocks sent to a block device (blocks/s). 每秒內存寫出多少個block到磁盤

2.4  使用 sar -b 查看磁盤IO

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

03:53:21 PM       tps      rtps      wtps   bread/s   bwrtn/s
03:53:23 PM      0.00      0.00      0.00      0.00      0.00
03:53:25 PM      0.00      0.00      0.00      0.00      0.00
03:53:27 PM      0.00      0.00      0.00      0.00      0.00
03:53:29 PM      0.00      0.00      0.00      0.00      0.00
Average:         0.00      0.00      0.00      0.00      0.00

tps: 上面有介紹;rtps: 表示讀的tps;wtps: 表示寫的tps;

bread/s: 每秒讀多少個block;bwrtn/s: 每秒寫多少個block;

2.5  使用 iotop 找到IO最多的進程/線程

iotop相似於top命令,默認按照IO排序:

iotop :

iotop 是能夠交互的

       Use  the  left  and  right arrows to change the sorting, r to reverse the sorting order, o to toggle the --only
       option, p to toggle the --processes option, a to toggle the --accumulated option, q to quit or i to change  the
       priority of a thread or a process’ thread(s). Any other key will force a refresh.
1)利用左右鍵 能夠選擇排序的字段,默認按照IO>倒序,能夠按照SWAPIN,DISK WRITE 等等字段排序,使用左右方向鍵便可;

2)利用 p鍵 能夠在按照 進程顯示 和按照 線程顯示之間切換;

3)r 鍵能夠改變排序的方向:倒序 和 順序

查看mysqld的IO

iotop -k -u mysql (-k 表示KB,-u mysql表示顯示mysql用戶的全部進程的IO):

3、實例分析

$$iostat -d -k 1 |grep sda10
Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda10            60.72        18.95        71.53  395637647 1493241908
sda10           299.02      4266.67       129.41       4352        132
sda10           483.84      4589.90      4117.17       4544       4076
sda10           218.00      3360.00       100.00       3360        100
sda10           546.00      8784.00       124.00       8784        124
sda10           827.00     13232.00       136.00      13232        136

上面看到,磁盤每秒傳輸次數平均約400;每秒磁盤讀取約5MB,寫入約1MB。

iostat -d -x -k 1
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.56  28.31  7.84 31.50   43.65    3.16    21.82     1.58     1.19     0.03    0.80   2.61  10.29
sda          1.98  24.75 419.80  6.93 13465.35  253.47  6732.67   126.73    32.15     2.00    4.70   2.00  85.25
sda          3.06  41.84 444.90 54.08 14204.08 2048.98  7102.04  1024.49    32.57     2.10    4.21   1.85  92.24

能夠看到磁盤的平均響應時間<5ms,磁盤使用率>80。磁盤響應正常,可是已經很繁忙了。

4、磁盤IO優化

磁盤IO在優化以前,首先要弄清楚系統的IO狀況,是隨機IO多,仍是順序IO多,是大文件IO多,仍是小文件IO多(小文件IO通常也就是隨機IO)。好比隨機IO多,那麼就能夠經過加磁盤使用RAID技術來優化,若是是順序IO遇到瓶頸,通常多是磁盤驅動的帶寬有瓶頸,就能夠換一個更快的disk controller。搞清楚是磁盤有瓶頸,仍是磁盤驅動的帶寬有瓶頸。

由於磁盤IO的操做分紅了4個層面,因此IO的優化也能夠從這四個方面入手:

1)正對mysql系統的調優,還須要選擇正確的IO調度算法,若是是SSD,選擇NOOP調度算法,若是是磁盤,那麼選擇deadline調度算法;

2)針對mysql還顯然能夠經過master-slave來讀寫分離進行磁盤IO優化,若是沒有master-slave架構,那麼能夠在前端加上memcache/redis緩存。

3)對於寫不少形成的壓力,則能夠適當的採用Nosql(redis/mongdb/ssdb)等將能夠分離出去的儘可能分離出去。

4)另外增大內存,能夠對更多的磁盤文件進行緩存,也能減輕IO壓力。

5)還有文件系統的掛載選項 noatime, nodiratime也能減輕IO壓力,另外選擇正確的文件系統也能提升磁盤的tps. mysql數據庫推薦使用XFS文件系統。

注:上面顯示的磁盤IO的數據,不少都是0,這是由於數據來自於虛擬機中的Linux系統。

相關文章
相關標籤/搜索