一 问题描述

一台Zabbix proxy收到持续IO报警信息。

xxxxx: High disk io on sdb for 5 minutes Trigger status: PROBLEM
 Bandwidth utilization for sdb (hk-zabbix-prod-proxy:disk.status[sdb,util]): 97.1 %

关于使用Zabbix监控磁盘IO可以参考

http://john88wang.blog.51cto.com/2165294/1545834




二 解决办法

登录这台服务器上先找出是什么程序在占用磁盘IO

使用 vmstat -S M 3

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 5  1      0    489    376  65049    0    0     0  1956 16554 13392  3  1 94  3  0	
 0  2      0    480    376  65057    0    0     0  4263 18374 12537  2  1 94  3  0	
 1  1      0    489    376  65047    0    0     0  2173 16294 13499  2  1 95  2  0	
 1  1      0    490    376  65046    0    0     0  4225 20427 15262  5  1 92  3  0	
 6  0      0    492    376  65046    0    0     0   988 15024 12345  2  3 93  2  0	
 0  1      0    491    376  65045    0    0     0  2068 14824 12619  3  1 94  2  0	
 6  1      0    483    376  65047    0    0     0  3404 17717 12316  1  1 95  3  0	
 0  1      0    493    376  65044    0    0     0  2084 13136 13430  1  1 95  3  0	
 1  1      0    480    376  65056    0    0     0  5292 14833 13194  3  1 92  3  0	
 3  1      0    476    376  65062    0    0     0  1484 11698 11063  2  1 95  3  0	
 1  0      0    493    376  65045    0    0     0 14237 11399 11245  1  1 96  2  0	
 1  0      0    490    376  65046    0    0     0  6484 12396 12582  2  1 95  2  0	
 1  0      0    469    376  65069    0    0     0  1564 13884 13044  5  1 92  2  0	
 0  1      0    492    376  65046    0    0     0  2589 12915 12921  2  1 95  2  0	


通过vmstat看出cpu的wa大概是%3,这里还看不出磁盘IO有多大的问题

继续使用iostat -xmt 3查看磁盘IO

05/18/2016 11:05:15 PM
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           1.51    0.00    1.13    2.38    0.00   94.99

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
sdb               0.00   267.00    0.00  161.33     0.00     1.67    21.21     0.88    5.41   5.03  81.20

05/18/2016 11:05:18 PM
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.10    0.00    1.02    2.54    0.00   94.35

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     3.67    0.00    2.00     0.00     0.02    22.67     0.02    9.67   4.00   0.80
sdb               0.00   534.33    0.00  181.67     0.00     2.79    31.50     0.99    5.45   4.96  90.17

05/18/2016 11:05:21 PM
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.25    0.00    1.65    2.93    0.00   93.16

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     1.67    0.00    1.00     0.00     0.01    21.33     0.01   13.33   6.00   0.60
sdb               0.00   241.67    0.00  186.00     0.00     1.66    18.31     1.21    6.50   4.99  92.90

05/18/2016 11:05:24 PM
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           3.29    0.00    3.06    2.86    0.00   90.79

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     2.33    0.00    1.00     0.00     0.01    26.67     0.01    5.33   3.33   0.33
sdb               0.00  1593.33    0.00  186.67     0.00     6.95    76.20     2.25   12.07   4.91  91.63


可以看出连续多次输出中,磁盘sdb的利用率都是85%以上


然后使用iotop查看哪些进程在使用io

wKiom1c9ZnCQ89LIAASUOOJqggg696.png

可以看出主要是MySQL在使用磁盘IO,但是怎么会有个奇怪的进程[jdb2/sdb1-8]占用那么高的磁盘IO


这里涉及到两个知识点

  1. 文件系统EXT4的journaling进程jdb2

  2. MySQL的磁盘写入调优


最快的解决方式就是关闭这个磁盘的journaling日志

tune2fs -O "^has_journal" /dev/sdb1 

但是不建议这样使用,因为关闭了EXT4的日志记录功能就存在丢失数据的风险。MySQL的InnoDB表即使关闭了EXT4的日志记录功能也能够不丢失数据,只要开启了innodb_doublewrite 参数,默认就是开启的。

innodb_doublewrite 参数开启后,InnoDB会存储所有的数据两次,先存储数据到doublewrite buffer,然后再存储数据到数据文件中。

mysql> show variables like '%double%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| innodb_doublewrite | ON    |
+--------------------+-------+
1 row in set (0.00 sec)


sync_binlog  

sync_binlog参数也会影响到MySQL数据库服务器的磁盘IO.如果这个变量的值大于0,MySQL server synchronizes its binary log to disk(using fdatasync()) after sync_binlog commit groups are written to the binary log.


innodb_flush_log_at_trx_commit    

这个参数默认值是1. 简单点说这个参数就是平衡InnoDB事务日志写入磁盘的频率和MySQL性能的一个参数。这个参数有3个取值

0   每次事务提交操作时不从log buffer中刷新日志到磁盘,InnoDB大约每秒从log buffer中刷新日志到磁盘,也就是说,如果发生MySQL崩溃,那么大约会丢失1秒的数据。

1   每次事务提交操作时都从log buffer中刷新日志到磁盘,这个是最安全的方式


2  InnoDB的log buffer中的数据在每次事务提交操作之后再刷新到磁盘,普通日志大约每秒刷新到磁盘。如果有MySQL崩溃或者断电等情况大约会丢失1秒的数据



对于Zabbix应用,丢失1秒数据的风险性不大。所以设置


innodb_flush_log_at_trx_commit = 0


再观察磁盘IO就恢复正常了




参考文档:

http://serverfault.com/questions/363355/io-wait-causing-so-much-slowdown-ext4-jdb2-at-99-io-during-mysql-commit

https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_doublewrite

https://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#sysvar_sync_binlog

https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html