磁盤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;
顯示單位問題:默認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數值很高;均可能預示着磁盤存在瓶頸或者磁盤出現問題或者故障。
上面查看的都是整個磁盤的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
[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到磁盤
[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;
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):
$$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。磁盤響應正常,可是已經很繁忙了。
磁盤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系統。