mysql服务器iowait高优化一例完整深入解析

 我们有一服务器,上面运行着两个mysql实例,这几天iowait一直很高,在20-30%,下午特地专门排查和解决了下,相关过程整理如下。

该服务器有两个挂载盘,服务器在阿里云上,一个系统盘,一个数据盘。

因为非生产库,测试kill -9 mysql-pid后,top如下:

虽然mysql占用内存释放了,但是swap还是占着,虽然swap没有释放,但其不一定会用到,如下:

可见,swap没有活动,但是io很高(block out),bo是写磁盘。

如果不放心swap占用的话,可以通过下列命令释放swap

# sync

# echo 3 > /proc/sys/vm/drop_caches

# swapoff -a

执行后,会将swap中缓存的数据刷新到磁盘,并逐渐释放,如下:

# swapon -a  # 启用swap

但是io还是很高,此时,可通过iotop确定是那些文件、哪些进程的io读写频繁,可知是mysqld和jbd2(ext4写日志的进程)为主,并且主要在vda盘。

 但是,仅仅iotop看不出每个磁盘设备的完整情况,此时可通过sar -d看每块盘的情况,如下:

 

由上图可知,主要是vda设备的写入特别繁忙。

DEV            磁盘设备
用参数-p可以打印出sda,hdc等磁盘设备名称,如果不用参数-p,设备节点则有可能是dev8-0,dev22-0
tps:每秒从物理磁盘I/O的次数.多个逻辑请求会被合并为一个I/O磁盘请求,一次传输的大小是不确定的.
rd_sec/s:每秒读扇区的次数.
wr_sec/s:每秒写扇区的次数.
avgrq-sz:平均每次设备I/O操作的数据大小(扇区).
avgqu-sz:磁盘请求队列的平均长度.
await:从请求磁盘操作到系统完成处理,每次请求的平均消耗时间,包括请求队列等待时间,单位是毫秒(1秒=1000毫秒).
svctm:系统处理每次请求的平均时间,不包括在请求队列中消耗的时间.
%util:I/O请求占CPU的百分比,比率越大,说明越饱

接下去,我们就可以通过pt-ioprofile查看io读写最多的文件(虽然pt-ioprofile是percona发布的,但是它同样可以查看其他程序比如java进程的io读写)。

 

需要注意的是,pt-ioprofile输出中每列含义的实际意义要根据上下文来说,没有直接的过高或者过低。在本例上,我们上述已经知道磁盘写是瓶颈,所以read/lseek需要忽略。

pwrite/write是消耗iowait的主要部分。

在我们的问题中,data/data2是两个实例的data_dir,都在vda挂载的FS中,所以我们需要将其移动到vdb才能缓解。

因为移动整个实例不太现实,所以,我们打算移动部分文件到vdb。注:iowait的比例范围跟磁盘数有关,越多,iowait可能的值越大。

现在,来说下打算移动哪些文件。

oracle和mysql最大的差别在于:

oracle不存在引擎插件一说,所以,没有mysql的innodb_log和mysql_bin之分,同时mysql还有一个doublewrite文件,应该来说,任何时候这三个是最占据io的文件,data文件一般不会成为瓶颈。

从上可知,doublewrite是消耗大户,应该放到单独磁盘比较合适,只不过5.6版本之后,percona server去掉了innodb_doublewrite_file这个参数(percona 5.7新增了一个相关参数innodb_parallel_doublewrite_path,尚未仔细测试https://www.percona.com/doc/percona-server/5.7/performance/xtradb_performance_improvements_for_io-bound_highly-concurrent_workloads.html),mysql本身不支持自定义doublewrite的位置。所以,打算挪binlog和ib_log,故更改初始化参数innodb_log_group_home_dir=/VDB_DATA、log_bin=/VDB_DATA/mysql-bin、log_bin_index=/VDB_DATA/mysql-bin.index,重启mysql实例后,如下:

虽然vda依然繁忙,但是vdb已经分担了部分的io活动。

再进一步,我们可以通过ps -eLf找到23078线程所属进程,如下:

用ioprofile确定是哪个文件:

此时,主要是slave相关文件。

注意:在很多的优化文章或者PPT中,会见到建议将slave_master_info存储为innodb表,事实上在io是瓶颈的系统中,由于mysql实现体系的原因,将其存储在innodb中会加剧xb_doublewrite的活动,不一定能够达到更好的效果,甚至更差(https://dev.mysql.com/doc/refman/5.7/en/slave-logs.html)。

更改relay-log-index=/VDB_DATA/relay-bin.index,relay-log=/VDB_DATA/relay-bin,重启mysql实例后,如下:

调整后,io分布式是比较均匀了,但是可以发现vdb的iops明显低于vda,所以可能还需要进一步调整以达到较为满意的效果。

iops的测试,请参见拿到新服务器时应做的标准测试

 

posted @ 2017-03-14 19:46  zhjh256  阅读(1713)  评论(0编辑  收藏  举报