这是一篇实战性的文章,如何处理正在发生的MYSQL服务器CPU飙升的问题,一般情况下,MySQL是不会耗用这么高的CPU的,要么是不走索引的查询,要么是同一时间出现了大量比较耗用资源的查询,不管出现的是哪一种情况,都可以试着这么去排查问题的原因:

        MySQL是多线程模型,可以使用pidstat -t -p `pidof mysqld` 2命令查看系统中的哪些MySQL线程比较耗用CPU资源,也可以使用show processlist;查看MySQL正在运行的查询有哪些。大部分情况下,比较耗时的查询在show processlist中都会直接显形的。凡事都有例外,如果不是查询引起的问题,仍需要使用pidstat命令来确认高耗用CPU的线程。

        拿到了高耗用CPU的线程ID就可以通过查询,定位到具体的SQL语句,可以通过一个查询实现:select * from performance_schema.threads where thread_os_id=<线程ID>; 非常简单吧。

        如果是拿到了会话ID,也是可以通过查询来获得具体的SQL语句的,稍微改一下查询条件就可以了:select * from performance_schema.threads where prosess_id=<会话ID>; 同样非常简单。

        上面都是查询引起的问题,可以通过修改查询的实现,优化查询条件和添加索引来实现查询优化,降低CPU的占用率,查询问题基本上都能解决。

        那么如果是其它原因呢,比如后台刷脏页的问题,如果不幸遇到了这样的问题,可以先尝试调整MySQL中与刷脏页相关的参数。目标是让刷脏页的量变得比较平滑,避免突然出现大量的刷脏请求,能在后台慢慢刷脏页的,就不要让MySQL停止响应,只干刷脏页这一个事情,那么什么时候MySQL会停下来只干刷脏页这一个事情呢。这和MySQL运行的服务器内存,内核参数和MySQL的参数设置有关,单就MySQL的相关参数是:innodb_max_dirty_pages_pct, innodb_max_dirty_pages_pct_lwm 这两个参数分别用来设置允许的最大脏页数和什么时候开始慢慢刷脏页,那么刷脏页的速度和什么有关呢。从根本上说,肯定和系统磁盘性能有关,MySQL并不清楚系统磁盘的性能如何,而是通过另外两个参数来调整刷脏页的速率的,这两个参数分别是:innodb_io_capacity, innodb_io_capacity_max 分别用来设置默认刷脏页的速率和最大刷脏页的速率,MySQL会根据这两个值和前面的两个参数的值来设定刷脏页的速率。因为MySQL在刷脏页的同时还会进行其它的写盘操作,所以这个值一般会留有一定的余地,innodb_io_capacity_max略小于磁盘性能的最大值,innodb_io_capacity可以设置为磁盘最大性能的70%左右。多大合适,并没有固定的参考值,关键在于理解这些参数的意义,根据具体情况进行调整。

        如果调整参数也是解决不了刷脏页的问题的,就要考虑更换更高性能的磁盘了,目前SSD盘已经普及的情况下,一块靠谱的SSD盘,iops是很高的,可以根据具体的磁盘性能来设置这些参数,让MySQL充分利用系统硬件资源,才能展现最大的性能。

        MySQL出现慢响应时,不要慌张,可以大胆猜测问题原因,但要小心求证,用数据说话,不要妄下结论,细心分析问题点,找出问题点,往往就能够给出性价比较高的解决方案。