针对innodb_flush_method参数的理解和对比测试(mycat+mysql)

    mysql的innodb_flush_method这个参数控制着innodb数据文件及redo log的打开、刷写模式,对于这个参数,文档上是这样描述的:
有三个值:fdatasync(默认),O_DSYNC,O_DIRECT
默认是fdatasync,调用fsync()去刷数据文件与redo log的buffer
为O_DSYNC时,innodb会使用O_SYNC方式打开和刷写redo log,使用fsync()刷写数据文件
为O_DIRECT时,innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo logmysql

首先文件的写操做包括三步:open,write,flush
上面最常提到的fsync(int fd)函数,该函数做用是flush时将与fd文件描述符所指文件有关的buffer刷写到磁盘,而且flush完元数据信息(好比修改日期、建立日期等)才算flush成功。
使用O_DSYNC方式打开redo文件表示当write日志时,数据都write到磁盘,而且元数据也须要更新,才返回成功。
O_DIRECT则表示咱们的write操做是从MySQL innodb buffer里直接向磁盘上写。linux

这三种模式写数据方式具体以下:sql

fdatasync模式:写数据时,write这一步并不须要真正写到磁盘才算完成(可能写入到操做系统buffer中就会返回完成),真正完成是flush操做,buffer交给操做系统去flush,而且文件的元数据信息也都须要更新到磁盘。
O_DSYNC模式:写日志操做是在write这步完成,而数据文件的写入是在flush这步经过fsync完成
O_DIRECT模式:数据文件的写入操做是直接从mysql innodb buffer到磁盘的,并不用经过操做系统的缓冲,而真正的完成也是在flush这步,日志仍是要通过OS缓冲缓存

分别对这个三类模式进行对比测试:服务器

1、测试条件mysql优化

一、1000并发测试单表的增、删、改、查操做,测试表已经设置索引,基础数据量是一千五百多万条(未作分表分库)并发

二、测试环境:haproxy+2个mycat节点+3台mysql(第一台mysql为主节点,负责写,另外两台负责读)async

mysql服务器配置:8G内存,8核1.80Ghz CPU函数

三、mysql优化后配置参数:性能

max_connections=2000
innodb_buffer_pool_size=4G
join_buffer_size=1M
sort_buffer_size=1M
thread_cache_size=8
innodb_buffer_pool_instances=8
innodb_page_cleaners=4
innodb_purge_threads=1 #使用单独的清除线程按期回收无用数据的操做
innodb_max_dirty_pages_pct=90 #innodb主线程刷新缓存池中的数据,使脏数据比例小于90%
wait_timeout=300
###从节点增长以下配置
innodb_doublewrite=off
innodb_page_cleaners=8
innodb_read_io_threads=64
innodb_write_io_threads=64
read_buffer_size=1M

2、测试结果

一、datasync(默认),O_DSYNC这两种模式的磁盘IO比较高(只截取主节点mysql的监控图,由于两个从节点经过主节点同步数据,IO压力基本一致)

二、O_DIRECT模式的磁盘IO明显低了好多

这说明O_DIRECT模式是将数据直接从MySQL innodb buffer向磁盘写入,其写入磁盘的速度应该是会低于从操做系统buffer往磁盘写。

三、datasync(默认),O_DSYNC这两种模式的free内存降低很快(特别是datasync模式)

经过linux中查看,free内存减小,相应的cache就会增多,这与大量将数据写入到操做系统buffer中有关。

同时对比序号1中的磁盘IO变化状况图就发现,free内存越少,IO就越大,这与页交换频繁相符合(页换出越大,磁盘写入的压力越大):

四、O_DIRECT模式的free内存降低比较慢

五、对比其余测试结果以下:

从对比数据能够看出,O_DSYNC对CPU的压力最大,datasync次之,O_DIRECT最小;总体SQL语句处理性能和响应时间看,O_DSYNC都较差;O_DIRECT在SQL吞吐能力上较好(仅次于datasync模式),但响应时间倒是最长的。

3、初步结论

终上结果作出分析以下:

(1)在类unix操做系统中,文件的打开方式为O_DIRECT会最小化缓冲对io的影响,该文件的io是直接在用户空间的buffer上操做的,而且io操做是同步的,所以不论是read()系统调用仍是write()系统调用,数据都保证是从磁盘上读取的;因此IO方面压力最小,对于CPU处理压力上也最小,对物理内存的占用也最小;可是因为没有操做系统缓冲的做用,对于数据写入磁盘的速度会下降明显(表现为写入响应时间的拉长),但不会明显形成总体SQL请求量的下降(这有赖于足够大的innodb_buffer_pool_size)。

(2)O_DSYNC方式表示以同步io的方式打开文件,任何写操做都将阻塞到数据写入物理磁盘后才返回。这就形成CPU等待加长,SQL请求吞吐能力下降,insert时间拉长。

(3)fsync(int filedes)函数只对由文件描述符filedes指定的单一文件起做用,而且等待写磁盘操做结束,而后返回。fdatasync(int filedes)函数相似于fsync,但它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的元信息到磁盘。

 默认datasync模式,总体表现较好,由于充分利用了操做系统buffer和innodb_buffer_pool的处理性能,但带来的负面效果是free内存下降过快,最后致使页交换频繁,磁盘IO压力大,这会严重影响大并发量数据写入的稳定性。也就是说拥有了高性能,但不会有高稳定性(特别是mycat集群,在大量数据写入和各节点mysql数据同步压力下,IO是很大的)。为了解决这个问题,能够有个折中的办法,定时的对操做系统进行echo 3 >/proc/sys/vm/drop_caches,清理一下OS缓存,能够及时回收一部份内存(回收顺间对性能会有所影响)。

O_DIRECT模式网上一些评论认为是性能最好的,但本次测试的结果来看,性能并非很高,可是稳定性确实比较高,在大并发量读写操做中,可以较长时间运行,只是在第一次启动系统后测试,该模式一开始的响应时间确实比较长,到后面才恢复到较低水平(分析的缘由是由于有两个mysql节点变成写模式了,可能重启mysql出现读写状态变化,在作这个测试时因为开发人员还配了Galera,两节点同时写入是基于row级的,因此开始很容易引发锁,响应时间就变得很慢),以下所示:

 

总结:对于mycat读写分离中,写数据压力小,读数据压力大的状况下,而且内存够大,innodb_buffer_pool_size配置够大的状况下,其实三种模式应该都行,读数据的性能基本是依赖于缓存,若是从稳定性和内存使用状况来考虑,用O_DIRECT模式会更好些,并经过优化查询以弥补响应时间不够快的问题。对于读写压力都很大或只是写的压力大的状况下,建议用datasync模式,并配上按期清理系统缓存的机制。若是咱们充分应用了mycat的分表分库和读写分离机制,那么对于总体系统的性能和稳定性都有帮助(由于大库和大表,都会严重下降数据的写入和读出性能,这样的话光是靠innodb_flush_method的模式配置也是治标不治本)。

至于,生产环境如何设置必定要以压测结果为准,以实际效果为准,不能盲目信任经验值。

跟你们推荐一个学习资料分享群:747981058,里面大牛已经为咱们整理好了许多的学习资料,有自动化,接口,性能等等的学习资料!人生是一个逆水行舟的过程,不进则退,我们一块儿加油吧!