今天,将一个环境切换成行情优化后的版本后,发现io等待还是挺高,这还是第一次出现的。其他很多套环境都没有这个问题了,故iotop看了下,基本可以确定为是mysql进程的问题,如下:
但是iotop只能看到进程级别,对于rdbms而言,通常力度并不够,此时需要进一步使用其他工具比如io-profile(io-profile需要安装percona-toolkit,具体可搜索网上,比如http://www.cnblogs.com/zping/p/5678652.html),可以进一步attach到具体的进程,然后定位到具体的文件,如下:
[root@iZbp112kwadw1qt8emked5Z local]# pt-ioprofile --profile-pid=26256 --cell=sizes --run-time=30 Fri Feb 17 10:57:45 CST 2017 Tracing process ID 26256 total pread read pwrite write fsync open close lseek fcntl filename 64987456040 9890596 48180 0 0 0 0 0 64977517264 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/mysql/proc.MYD 17101824 0 0 17101824 0 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/ib_logfile0 8159232 0 0 8159232 0 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_act/tb_act_stock_quotation_tmp.ibd 5329976 137 591 5308416 0 0 0 0 20832 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_sys/tb_sys_stock_info_tmp.ibd 1474560 0 0 1474560 0 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/ibdata1 632856 3400 14800 114688 0 0 0 0 499968 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_sys/tb_sys_stock_info_tmp.frm 564372 4150 18590 0 0 0 0 0 541632 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_act/tb_act_stock_quotation_tmp.frm 132508 0 0 0 132508 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/mysql-bin.000056 15028 0 0 0 15028 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/iZbp112kwadw1qt8emked5Z.err 9189 0 0 0 9189 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/iZbp112kwadw1qt8emked5Z-slow.log 2742 0 0 0 0 0 0 0 2742 0 /tmp/ibpJOVg5 0 0 0 0 0 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_sys/tb_sys_stock_info.ibd 0 0 0 0 0 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_rsk/tb_rsk_compliancecalcservice.ibd 0 0 0 0 0 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_act/tb_act_stock_quotation.ibd [root@iZbp112kwadw1qt8emked5Z local]#
pread/read/pwrite/write的区别如下:
内核文件I/O->标准库I/O->高级I/O->IPC
关于read/pread和write/pwrite的解释,可以参考http://www.cnblogs.com/brill/p/3226439.html,但是关于引入pread/pwrite的背景原因,应该来说现行网上的解释都不是很好,只有帖子http://tieba.baidu.com/p/2850517299的一个答复者精确的说明了这个问题,如下:
首先pread、pwrite提出的背景是早期的UNIX没有正确地实现O_APPEND,因而引入一对原子操作,来解决append过程中的“脏写”问题。解决方法就是靠第四个参数来给每个进程(线程)分配各自的读写空间,避免它们的读写空间相互覆盖。前提是程序员清楚地知道每个线程需要多大的读写空间。
其次,如果有循环读写的需求,也需要修改第四个参数,从而改变起始位置。
总之,pread、pwrite是一对很实用的随机读写接口。
很多框架或者类库发展到成熟版本后,很多特性或者接口为何以当前这样的方式实现或者提供,有时候真得知道或者了解当时的技术限制、业务场景,才能领会,否则很可能就是觉得很多今天看起来很普通的特性、为什么框架作者绕了一个大圈子来实现。
在我们的系统中,因为大量使用了存储过程,所以导致proc.MYD的lseek奇高。而tb_act_stock_quotation_tmp.ibd和tb_sys_stock_info_tmp.ibd则是load infile local到innodb文件所致。将这两个表的引擎改成memory后,io等待就降低到1%以下,而且从io-profile中消失了,如下:
[root@iZbp112kwadw1qt8emked5Z logs]# pt-ioprofile --profile-pid=26256 --cell=sizes --run-time=30 Fri Feb 17 11:25:23 CST 2017 Tracing process ID 26256 total pread read pwrite write fsync open close lseek filename 68397517302 9658786 49780 0 0 0 0 0 68387808736 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/mysql/proc.MYD 4276736 0 0 4276736 0 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/ib_logfile2 1991058 13836 60678 0 0 0 0 0 1916544 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_sys/tb_sys_stock_info_tmp.frm 138261 0 0 0 138261 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/mysql-bin.000056 86948 660 2960 0 0 0 0 0 83328 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/db_act/tb_act_stock_quotation_tmp.frm 16041 0 0 0 16041 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/iZbp112kwadw1qt8emked5Z.err 2742 0 0 0 0 0 0 0 2742 /tmp/ibpJOVg5 460 0 0 0 460 0 0 0 0 /usr/local/Percona-Server-5.6.31-rel77.0-Linux.x86_64.ssl101/data/iZbp112kwadw1qt8emked5Z-slow.log
但是,这个时候绝大部分的读写都在mysql/proc.MYD,该文件保存是mysql存储过程的表所存储的文件。
因为proc.MYD是MyIsam表,它只能cache index,mysql层面无法缓存data,要解决这个问题,就得看看有没有方法在linux层面将其缓存起来。