描述:
程序反映当一个游戏服开服一段时间后,其使用的MySQL每隔一段时间都会出现几十条慢日志,慢日志集中在1到2秒内连续刷出,卡顿平均在60秒左右。一天当中每个时间段都有概率出现,即使是半夜3,4点没什么玩家的时候。
定位(trouble troubleshooting):
根据描述,基本排除是程序代码的问题,因为游戏高峰期打世界BOSS的时候(每天中午12点玩家最活跃的时候)都不会出现慢日志,就算再慢也不会真的有60秒的卡顿。即使如此还是先每秒执行一次show processlist命令进行监控,当慢日志出现时,可以看看是哪些sql语句在执行并且卡住。结果发现每次出现慢日志时,不管是什么sql语句,都会在执行commit阶段的时候卡住。
commit是指提交事务,每次提交事务时都会去写innodb的事务日志和binlog日志,这些日志每写到一定的大小会进行轮转,这个过程会锁住当前正在写的日志文件,把数据彻底刷到磁盘,然后新建一个日志文件并将日志写到这个新的文件中,如果这个过程持续过长,那么应用程序新产生的commit势必会卡住。故怀疑如此多的commit定时卡住跟日志文件的轮转有关,进一步调查发现每次binlog文件的轮转必定会产生的新的慢日志,当轮转结束后慢日志消失,所以问题定位在binlog的轮转上。
尝试:
一开始尝试优化binlog的相关配置参数,比如sync_binlog设为0,减轻binlog的IO压力,max_binlog_cache_size默认为1G,把它设小一些降低轮转时的IO,结果发现还是会处理慢日志,只不过卡顿时间由平均的60秒降低到10秒