当使用公有云关系存储数据库服务时,经常会对IOPS做限制,导致数据库如果操作频繁,经常会达到限制,特别是inser,update,delete这类需要操作写入磁盘的。本篇讲讲IOPS是什么,为什么会高,以及Mysql的处理方案。
什么是IOPS简单的理解就是每秒的磁盘操作次数。
为什么会高当每次insert,update时, 写入的磁盘次数就会变高。
我们查看mysql的文件也能发现有几个很大的文件:
是的,这几个大文件应该就是导致写入磁盘每秒次数过高的原因。
我们分别对号入座下:
undoxxx 对应 undo log
ib_logfilexxx 对应 redo log
binlog 对应 binlog
不知这几个日志大家是否眼熟?在insert,update,delete操作时,会写入这些日志,下面详细讲解下这些日志是做什么用的。
上面两个是属于innodb引擎特有。
binlog是mysql server特有的,记录的都是事务操作内容。undo/redo log和binlog的记录时机也不同, 前者在事务执行过程中会不断的写入,后者是在事务最终提交前写入的。
结论:那也就是说如果没有任何优化,有可能1次insert操作至少会有3次磁盘的写入,导致量大了后IOPS过高。
IOPS过高时的处理方案针对undo/redo log 和 binlog的写入磁盘机制, mysql其实提供了参数可以进行配置:
innodb_flush_log_at_trx_commit配置此项配置用来针对undo/redo log的磁盘写入配置。他有3个类型:
设置为0:会每隔1秒把缓存中的undo/redo log写入到磁盘。
设置为1:每次提交事务(一般的insert和update都有事务)写入到磁盘,该方案最安全,也是最慢的。
设置为2:会写入系统的缓存,但会每隔一秒才调用文件系统的“flush”将缓存刷新到磁盘上去。这样mysql即使崩了,系统缓存还在,比0的方案优。
所以通过配置注释看到,如果我们可以在数据库服务器宕机的时候,允许有1秒的数据丢失,其实用设置为2是最优的方案,可以提高性能。
查看当前配置的代码:
show variables like 'innodb_flush_log_at_trx_commit';
设置的代码(立即生效,无需重启):
set global innodb_flush_log_at_trx_commit=2;
sync_binlog配置
此项配置用来针对binlog的磁盘写入配置,可以用来配置合并多少条binlog一次性写入磁盘。
设置为0:代表依赖系统执行合并写入。
设置为1:代表每次提交事务后都需要写入,方案最安全,也是最慢的。
设置为N(一般100-1000): 代表每N条后,合并写入磁盘。
针对sync_binlog,同样允许数据库服务器宕机的情况下能接受丢失N条数据的, 可以配置为N,能提高性能。
查看当前配置的代码:
show variables like 'sync_binlog';
设置的代码(立即生效,无需重启):
set global sync_binlog=100;
总结
经过上面操作,也就是多sync_binlog和innodb_flush_log_at_trx_commit两个参数的配置进行重新定义后,生产环境中的确降低了IOPS。
但是关系型数据库最注重的是ACID特性,按照优化的配置也就破坏了这个特性,所以有利的时候同时也存在着弊端,只适合数据允许接收丢失的情况。如果实在不能接收丢失,只要依靠分布式的方式,也就是增加处理能力,来支持业务所需的IOPS。