MySQL 性能优化(INNODB下修改表结构)

    最近碰到一个奇怪的问题:在MySQL中修改一个大表的结构(增加一列),发现修改缓慢无比,表是用的INNODB引擎,大小大概6G的样子!按道理修改表结构应该会很快(因为CPU耗费不是很大,无非就是读就数据写入新的文件),由于执行时间超出了预期,所以该想办法解决了(要感谢我一位无所不能的伟大的同事 :)

    分析问题:
       MYSQL修改表结构时,会从旧表中读取数据,然后写入临时表(和旧表在同一目录下,命名方式为#sql_MySQLID_ConnnectID的形式),所以假设你的磁盘IO是100M/S的话,每秒理想的情况是临时表以50M/S在增加 :) ).而实际发现速度只有1M/S

    解决过程:

  1. 查看生成临时文件的大写变化(与机器的IO能力严重不符)
  2. 通过Top查看CPU,IO,内存使用情况,发现CPU,内存占用率非常低,根本没有跑起来,而总是在IOWait;
  3. 通过IOStat查看IO,发现IO Write有10M/S(说明在狂写数据,与临时文件大小变化严重不符,当然达不到50M/S,因为要做很多Check)
  4. 接着通过df查看磁盘空间的变化,发现1M/S(对应临时表的增加),也就是数据写出来了,但是在磁盘上看不见(太不应该了)
  5. 感觉应该是写日志之类的影响了性能(拼命写日志,然后又删掉,再写再删……)

    结论:
    MySQL的INNODB引擎会做文件恢复(通过记录操作日志来恢复数据),修改参数innodb_log_file_size为512M(默认5M),问题解决性能提升了10倍以上 :) 。因为MySQL对这种改动完全做了日志记录基本上表有多大日志就有多大(那为什么不是性能不是提升了2倍呢?后面再说)

    教训:

  1. 解决问题的过程很值得学习!

    为什么性能是提升了10倍以上呢?每当日志文件写满后,最差的解决方案:关闭文件、删除文件、新建日志文件、重新开始写(请思考这个过程中的代价,打开、关闭特别费时间);最好的解决方案:写满后fseek到日志开头重新开始写(一次seek的代价,事实上MySQL使用两个同样的日志文件进行轮回的)。所以时刻记住fseek是一个奢侈的东西

    其实这个问题有点弱智(疏忽),但是解决过程很有意思 :)   和这个问题相关的还有写参数可以调整,但是都不是瓶颈所以不多说了。

    参考资料:
    http://www.muduo.net/index.php/uid-8974-action-viewspace-itemid-175571
    http://nalai.net/content/view/305050/32/

觉得文章有用?立即: 和朋友一起 共学习 共进步!

猜您喜欢

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>