关闭

SSD下的MySQL IO优化

发表于:2015-9-01 09:42

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:温国兵    来源:51Testing软件测试网采编

  六 程序切换之前调优
  程序切换之前,39 只是 24 的从库,所以 IO 压力不高,以下的调整也不能说明根本性的变化。需要说明一点,以下调整的平均间隔在 30 分钟左右。
  6.1 修改系统 IO 调度算法
  系统默认的 I/O 调度算法 是 CFQ,我们试图先修改之。至于为什么修改,可以查看第四节。
  具体的做法如下,需要注意的是,请根据实际情况做调整,比如你的系统中磁盘很可能不是 sda。
  echo “noop” > /sys/block/sda/queue/scheduler
  如果想永久生效,需要更改 /etc/grup.conf,添加 elevator,示例如下:
  kernel /vmlinuz-x.x.xx-xxx.el6.x86_64 ro root=UUID=e01d6bb4-bd74-404f-855a-0f700fad4de0 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun1
  6 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM elevator=noop rhgb quiet
  此步调整做完以后,查看 39 I/O 状态,并没有显著的变化。
  6.2 修改 innodb_io_capacity = 4000
  在做这个参数调整之前,我们来看看当前 MySQL 的配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 200
  innodb_max_dirty_pages_pct 30
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  修改方法如下:
  SET GLOBAL innodb_io_capacity = 4000;
  网络上的文章,针对 SSD 的优化,MySQL 方面需要把 innodb_io_capacity 设置为 4000,或者更高。然而实际上,此业务 UPDATE 较多,每次的修改量大概有 20K,并且基本上都是离散写。innodb_io_capacity 达到 4000,SSD 并没有给整个系统带来很大的性能提升。相反,反而使 IO 压力过大,until 甚至达到 80% 以上。
  6.3 修改 innodb_max_dirty_pages_pct = 25
  修改方法如下:
  SET GLOBAL innodb_max_dirty_pages_pct = 25;
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 4000
  innodb_max_dirty_pages_pct 25
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  之前已经将 innodb_max_dirty_pages_pct 设置为 30,此处将 innodb_max_dirty_pages_pct 下调为 25%,目的为了查看脏数据对 I/O 的影响。修改的结果是,I/O 出现波动,innodbBuffPoolPagesFlushed 同样出现波动。然而,由于 39 是 24 的从库,暂时还没有切换,所有压力不够大,脏数据也不够多,所以调整此参数看不出效果。
  6.4 修改 innodb_io_capacity = 2000
  修改方法不赘述。
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 2000
  innodb_max_dirty_pages_pct 25
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  因为 innodb_io_capacity 为 4000 的情况下,I/O 压力过高,所以将 innodb_io_capacity 调整为 2000。调整后,w/s 最高不过 2000 左右,并且 I/O until 还是偏高,最高的时候有 70%。我们同时可以看到,I/O 波动幅度减小,innodbBuffPoolPagesFlushed 同样如此。
  6.5 修改 innodb_io_capacity = 1500
  修改方法不赘述。
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 1500
  innodb_max_dirty_pages_pct 25
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  I/O 持续出现波动,我们接着继续下调 innodb_io_capacity,调整为 1500。I/O until 降低,I/O 波动幅度继续减小,innodbBuffPoolPagesFlushed 同样如此。
  6.6 关闭 innodb_adaptive_flushing
  修改方法如下:
  SET GLOBAL innodb_adaptive_flushing = OFF;
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 1500
  innodb_max_dirty_pages_pct 25
  innodb_adaptive_flushing OFF
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  既然落地仍然有异常,那我们可以试着关闭 innodb_adaptive_flushing,不让 MySQL 干预落地。调整的结果是,脏数据该落地还是落地,并没有受 I/O 压力的影响,调整此参数无效。
  6.7 打开 innodb_adaptive_flushing
  修改方法如下:
  SET GLOBAL innodb_adaptive_flushing = ON;
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 1500
  innodb_max_dirty_pages_pct 25
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  经过以上调整,关闭 innodb_adaptive_flushing 没有效果,还是保持默认打开,让这个功能持续起作用吧。
  6.8 设置 innodb_max_dirty_pages_pct = 20
  修改方法不赘述。
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 1500
  innodb_max_dirty_pages_pct 20
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  接着我们将 innodb_max_dirty_pages_pct 下调为 20,观察脏数据情况。由于 InnoDB Buffer Pool 设置为 40G,20% 也就是 8G,此时的压力达不到此阀值,所以调整参数是没有效果的。但业务繁忙时,就可以看到效果,落地频率会增高。
  6.9 设置 innodb_io_capacity = 1000
  修改方法不赘述。
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 1000
  innodb_max_dirty_pages_pct 20
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  经过以上调整,我们需要的是一个均衡的 IO,给其他进程一些余地。于是把 innodb_io_capacity 设置为 1000,此时可以看到 I/O until 维持在 10% 左右,整个系统的参数趋于稳定。
  后续还要做进一步的监控、跟踪、分析和优化。
  七 程序切换之后调优
  在业务低峰,凌晨 1 点左右,配合研发做了切换。切换之后的主从关系可以查看第五节。
  7.1 设置 innodb_max_dirty_pages_pct = 30,innodb_io_capacity = 1500
  修改方法不赘述。
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 1500
  innodb_max_dirty_pages_pct 30
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  在 innodb_io_capacity 为 1000,innodb_max_dirty_pages_pct 为 20 的环境下,I/O until 有小幅波动,而且波峰和波谷持续交替,这种情况是不希望看到的。innodbBuffPoolPagesFlushed 比较稳定,但 innodbBuffPoolPagesDirty 持续上涨,没有下降的趋势。故做了如下调整:innodb_max_dirty_pages_pct = 30,innodb_io_capacity = 1500。调整完成后,innodbBuffPoolPagesDirty 趋于稳定,I/O until 也比较稳定。
  7.2 设置 innodb_max_dirty_pages_pct = 40,innodb_io_capacity = 2000
  修改方法不赘述。
  修改之后的 MySQL 配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 2000
  innodb_max_dirty_pages_pct 40
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  针对目前这种 I/O 情况,做了如下调整:innodb_max_dirty_pages_pct = 40,innodb_io_capacity = 2000。
  7.3 分析
  针对以上两个调整,我们通过结合监控数据来分析 I/O 状态。
  以下是高速缓冲区的脏页数据情况,如图二:
  
  以下是脏数据落地的情况,如图三
  
  28 号早 8 点到下午 7 点,当脏数据上升,也就是在内存中的数据更多,那么落地就会很少,呈现一个平稳的趋势;当脏数据维持不变,也就是脏数据达到了 innodb_max_dirty_pages_pct 的限额(innodb_buffer_pool_size 为 40G,innodb_max_dirty_pages_pct 为 40%,也就是在内存中的脏数据最多为 16G,每个 Page 16K,则 innodbBufferPoolDirtyPages 最大为 1000K),落地就会增多,呈现上升的趋势,所以才会出现上述图片中的曲线。
  这是最后的配置:
  innodb_buffer_pool_size 42949672960
  innodb_log_file_size 1342177280
  innodb_io_capacity 2000
  innodb_max_dirty_pages_pct 40
  innodb_adaptive_flushing ON
  innodb_write_io_threads 4
  innodb_read_io_threads 4
  八 小结
  此次针对 SSD 以及 MySQL InnoDB 参数优化,总结起来,也就是以下三条:
  修改系统 I/O 调度算法;
  分析 I/O 情况,动态调整 innodb_io_capacity 和 innodb_max_dirty_pages_pct;
  试图调整 innodb_adaptive_flushing,查看效果。
  针对 innodb_write_io_threads 和 innodb_read_io_threads 的调优我们目前没有做,我相信调整为 8 或者 16,系统 I/O 性能会更好。
  还有,需要注意以下几点:
  网络文章介绍的方法有局限性和场景性,不能亲信,不能盲从,做任何调整都要以业务优先。保证业务的平稳运行才是最重要的,性能都是其次;
  任何一个调整,都要建立在数据的支撑和严谨的分析基础上,否则都是空谈;
  这类调优是非常有意义的,是真正能带来价值的,所以需要多下功夫,并且尽可能地搞明白为什么要这么调整。
  文末,说一点比较有意思的。之前有篇文章提到过 SSDB。SSDB 底层采用 Google 的 LevelDB,并支持 Redis 协议。LevelDB 的设计完全是贴合 SSD 的设计思想的。首先,尽可能地转化为连续写;其次,不断新增数据文件,防止同一位置不断擦写。另外,SSDB 的名字取得也很有意思,也很有水平。我猜想作者也是希望用户将 SSDB 应用在 SSD 上吧。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号