磁盘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系统。