1. IO处理过程

磁盘IO经常会成为系统的一个瓶颈,特别是对于运行数据库的系统而言。数据从磁盘读取到内存,在到CPU缓存和寄存器,然后进行处理,最后写回磁盘,中间要经过很多的过程,下图是一个以write为例的 Linux 磁盘IO子系统的架构:

可以看到IO操作分成了四个层面:

1)文件系统缓存:处理数据必须先从磁盘读到缓存,然后修改,然后刷会磁盘。缓存的刷新涉及到两个参数:vm.dirty_background_ratio、vm.dirty_ratio。还有刷新写回时,使用到 bio 结构,bio的组成是由磁盘上相邻的block组成的,所以这里进行了优化。

2)block layer:该层就涉及到 IO调度算法,IO调度算法在mysql服务器是一个很重要的调优手段。系统中所有进程申请的IO操作,全部在这里进行排队,等待调度,然后写回磁盘。调度算法有四种:

1> Anticipatory: 适用于个人PC,单磁盘系统;

2> CFQ(Complete Fair Queuing):默认的IO调度算法,完全公平的排队调度算法。每一个进程的IO请求会安排进一个专门的IO队列,然后按照进程组来公平的调度IO,也就是每一个进程组之间按照公平的方式来调度IO。显然他适合多用户的系统,但是极为不适合作为数据库系统的IO调度算法,因为显而易见,数据库系统中,数据库进程肯定是IO最多的一个进程组,然后它却只能获得和其它进程一样多的IO调度机会。所以显然这是极为不合理的。数据库系统绝对不要使用该调度算法

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调度算法

临时修改

  1. [root@localhost ~]# cat /sys/block/sda/queue/scheduler
  2. noop anticipatory deadline [cfq]
  3. [root@localhost ~]# echo noop > /sys/block/sda/queue/scheduler
  4. [root@localhost ~]# cat /sys/block/sda/queue/scheduler
  5. [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 : 该选项显示具体的扩展信息;

  1. [root@localhost ~]# iostat
  2. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  3.  
  4. avg-cpu: %user %nice %system %iowait %steal %idle
  5. 0.60 0.00 7.80 0.31 0.00 91.30
  6.  
  7. Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
  8. scd0 0.02 0.21 0.00
  9. sda 2.00 78.60 8.43 [root@localhost ~]# iostat -c
  10. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  11.  
  12. avg-cpu: %user %nice %system %iowait %steal %idle
  13. 0.48 0.00 6.51 0.25 0.00 92.76
  14. [root@localhost ~]# iostat -d -k
  15. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  16.  
  17. Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
  18. scd0 0.02 0.08 0.00
  19. sda 1.69 31.17 4.15
  20.  
  21. [root@localhost ~]# iostat -d -m
  22. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  23.  
  24. Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn
  25. scd0 0.02 0.00 0.00
  26. sda 1.69 0.03 0.00
  27.  
  28. [root@localhost ~]# iostat -d -m -x
  29. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  30.  
  31. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  32. scd0 0.02 0.00 0.02 0.00 0.00 0.00 10.94 0.00 4.96 4.88 0.01
  33. sda 1.22 0.48 1.13 0.56 0.03 0.00 41.66 0.01 6.83 5.27 0.89
  34.  
  35. [root@localhost ~]# iostat -d -m -x 2 3
  36. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  37.  
  38. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  39. scd0 0.02 0.00 0.01 0.00 0.00 0.00 10.94 0.00 4.96 4.88 0.01
  40. sda 1.19 0.48 1.10 0.55 0.03 0.00 41.52 0.01 6.81 5.25 0.87
  41.  
  42. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  43. scd0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  44. sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  45.  
  46. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  47. scd0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  48. sda 0.00 0.00 0.00 0.51 0.00 0.00 8.00 0.00 3.00 3.00 0.15
  49.  
  50. [root@localhost ~]# iostat -y -d -m -x 2 3
  51. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  52.  
  53. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  54. scd0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  55. sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  56.  
  57. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  58. scd0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  59. sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  60.  
  61. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  62. scd0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  63. 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情况:

  1. [root@localhost ~]# iostat -x -d -m -p sda 2 3
  2. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  3.  
  4. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  5. sda 0.82 0.43 0.76 0.52 0.02 0.00 38.49 0.01 6.27 4.82 0.62
  6. sda1 0.80 0.42 0.53 0.51 0.02 0.00 45.09 0.01 6.92 5.50 0.57
  7. sda2 0.01 0.02 0.12 0.01 0.00 0.00 9.70 0.00 2.95 2.79 0.04
  8. sda3 0.01 0.00 0.07 0.00 0.00 0.00 8.67 0.00 3.72 3.65 0.03
  9.  
  10. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  11. sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  12. sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  13. sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  14. sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  15.  
  16. Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
  17. sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  18. sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  19. sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  20. sda3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  21.  
  22. [root@localhost ~]# iostat -d -m -p sda 2 3
  23. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  24.  
  25. Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn
  26. sda 1.25 0.02 0.00
  27. sda1 1.02 0.02 0.00
  28. sda2 0.13 0.00 0.00
  29. sda3 0.07 0.00 0.00
  30.  
  31. Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn
  32. sda 0.00 0.00 0.00
  33. sda1 0.00 0.00 0.00
  34. sda2 0.00 0.00 0.00
  35. sda3 0.00 0.00 0.00
  36.  
  37. Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn
  38. sda 0.00 0.00 0.00
  39. sda1 0.00 0.00 0.00
  40. sda2 0.00 0.00 0.00
  41. sda3 0.00 0.00 0.00

2.3 使用 vmstat 查看磁盘IO

  1. [root@localhost ~]# vmstat 2 4
  2. procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
  3. r b swpd free buff cache si so bi bo in cs us sy id wa st

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

  1. [root@localhost ~]# sar -b 2 4
  2. Linux 2.6.-.el6.i686 (localhost.localdomain) // _i686_ ( CPU)
  3.  
  4. :: PM tps rtps wtps bread/s bwrtn/s
  5. :: PM 0.00 0.00 0.00 0.00 0.00
  6. :: PM 0.00 0.00 0.00 0.00 0.00
  7. :: PM 0.00 0.00 0.00 0.00 0.00
  8. :: PM 0.00 0.00 0.00 0.00 0.00
  9. 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. 实例分析

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

上面看到,磁盘每秒传输次数平均约400;每秒磁盘读取约5MB,写入约1MB。

  1. iostat -d -x -k 1
  2. Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
  3. 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
  4. 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
  5. 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系统。

MySQL 调优基础(四) Linux 磁盘IO的更多相关文章

  1. MySQL 调优基础(五) Linux网络

    1. TCP/IP模型 我们一般知道OSI的网络参考模型是分为7层:“应表会传网数物”——应用层,表示层,会话层,传输层,网络层,数据链路层,物理层.而实际的Linux网络层协议是参照了OSI标准,但 ...

  2. MySQL 调优基础(二) Linux内存管理

    进程的运行,必须使用内存.下图是Linux中进程中的内存的分布图: 其中最重要的 heap segment 和 stack segment.其它内存段基本是大小固定的.注意stack是向低地址增长的, ...

  3. MySQL 调优基础:Linux内存管理 Linux文件系统 Linux 磁盘IO Linux网络

    http://www.cnblogs.com/digdeep/category/739915.html

  4. MySQL 调优基础(三) Linux文件系统

    Linux的文件系统有点像MySQL的存储引擎,它支持各种各样的文件系统.它最上层是通过 virtual files system虚拟文件系统作为一个抽象接口层来对外提供调用的.然后下层的各种文件系统 ...

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

    一般而言,MySQL 的调优可以分为两个层面,一个是在MySQL层面上进行的调优,比如SQL改写,索引的添加,MySQL各种参数的配置:另一个层面是从操作系统的层面和硬件的层面来进行调优.操作系统的层 ...

  6. mysql调优 基础

    MySQL调优可以从几个方面来做: 1. 架构层:做从库,实现读写分离: 2.系统层次:增加内存:给磁盘做raid0或者raid5以增加磁盘的读写速度:可以重新挂载磁盘,并加上noatime参数,这样 ...

  7. MySQL调优基础, 与hikari数据库连接池配合

    1.根据硬件配置系统参数 wait_timeout  非交互连接的最大存活时间, 10-30min max_connections   全局最大连接数 默认100 根据情况调整 back_log   ...

  8. 语句调优基础知识-set statistics io on

    set statistics io on --清空缓存数据 dbcc dropcleanbuffers go --清空缓存计划 dbcc freeproccache go set statistics ...

  9. MySQL调优系列基础篇

    前言 有一段时间没有写博客了,整天都在忙,上班,录制课程,恰巧最近一段时间比较清闲,打算弄弄MYSQL数据库. 关于MySQL数据库,这里就不做过多的介绍,开源.免费等特性深受各个互联网行业喜爱,尤其 ...

随机推荐

  1. 互联网背景时代下的大机遇,为什么用nosql

    1.单机MySQL的美好年代 在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付.在那个时候,更多的都是静态网页,动态交互类型的网站不多. 上述架构下,我们来看看数据存储的瓶颈是什么 ...

  2. java servlet调用带有多个返回结果集的存储过程

    一.mysql存储过程 这里我先说下我这个功能实现的逻辑及途中遇到的一些问题.这个存储过程一共带两个输入参数,一共关联到两张表的查询,每个参数都对应查询表中的一个判断,所以一共返回了两个结果集(当然要 ...

  3. Java--concurrent并发包下阻塞队列介绍

    JDK提供了7中阻塞队列,这里介绍其中3中,剩余的以此类推原理相同. 1.ArrayBlockingQueue package com.seeyon.queue; import java.util.c ...

  4. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  5. 利用Canvas编辑图片

    使用<canvas>对象在浏览器中把一幅彩色图片变成灰度图片. grayscale.html <!DOCTYPE html> <html lang="en&qu ...

  6. ahjesus Ubuntu配置svn服务器

    转载自http://www.cnblogs.com/ximu/articles/2119136.html 亲测可用 一.SVN安装1.安装包$ sudo apt-get install subvers ...

  7. nginx的pass_proxy遇到的坑

    Pass_proxy走内网,被请求方的php使用remote_addr得到就是转发机器的内网地址,如192.168.10.141这样的.走外网,被请求方php的remote_addr得到就是转发机器的 ...

  8. Linux下安装DB2_v9.7详细教程

    一:平台 1:HP服务器 cpu:Inter (R) Xeon (R) E5606 2.13G 磁盘:本地磁盘外加存储 2:操作系统 RedHet 5.4 64位 内核:2.6.18-194.1.AX ...

  9. 网上图书商城2--Category模块

    sql CREATE TABLE `t_category` ( `cid` char(32) NOT NULL, `cname` varchar(50) DEFAULT NULL, `pid` cha ...

  10. GJM : Unity3D 常用网络框架与实战解析 【笔记】

    Unity常用网络框架与实战解析 1.Http协议          Http协议                  存在TCP 之上 有时候 TLS\SSL 之上 默认端口80 https 默认端口 ...