暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

课程笔记:通过操作系统命令找到top sql| MySQL8.0-性能优化系列

原创 晨辉 2022-08-24
1058

适用范围

操作系统:Linux
数据库版本:MySQL 8

概述

当mysql数据库在运行CPU使用率很高时,需要找到是什么SQL消耗了很多的CPU,下面就是本课程中介绍的通过操作系统工具结合mysql性能视图来找到top sql的一种方法。

操作步骤

1)使用 top -H 命令找到cpu使用率高的线程(mysql数据库是单进程多线程,不能通过查找cpu高的进程来获取top sql)
如下可以看到5575的mysqld线程占用了98%的CPU
image.png
2)查看performance_schema.threads 性能视图查找该线程的详细信息

mysql> select * from performance_schema.threads where THREAD_OS_ID=5575\G;
*************************** 1. row ***************************
          THREAD_ID: 145
               NAME: thread/sql/one_connection
               TYPE: FOREGROUND
     PROCESSLIST_ID: 11
   PROCESSLIST_USER: root
   PROCESSLIST_HOST: localhost
     PROCESSLIST_DB: xhy
PROCESSLIST_COMMAND: Query
   PROCESSLIST_TIME: 216
  PROCESSLIST_STATE: executing
   PROCESSLIST_INFO: select count(*) from t t1,t t2 where t1.a<>t2.a
   PARENT_THREAD_ID: NULL
               ROLE: NULL
       INSTRUMENTED: YES
            HISTORY: YES
    CONNECTION_TYPE: Socket
       THREAD_OS_ID: 5575
     RESOURCE_GROUP: USR_default
1 row in set (0.00 sec)

ERROR: 
No query specified

可以看到5575的线程执行的SQL语句为select count(*) from t t1,t t2 where t1.a<>t2.a,执行了216秒,还正在执行。
下面通过kill 杀掉该线程应急来降低CPU
使用kill query 线程id(PROCESSLIST_ID值)杀掉该查询语句(会话还存在)

mysql> kill query 11;
Query OK, 0 rows affected (0.00 sec)

image.png
杀掉之后,CPU降到了10% 以下。
image.png
如果使用kill (PROCESSLIST_ID值)方式可以看到会话可能会重启,原来语句继续执行。
image.png
image.png

下面我们再看下5094的线程(占用了7.6%的CPU)

mysql> select * from performance_schema.threads where THREAD_OS_ID=5094\G;
*************************** 1. row ***************************
          THREAD_ID: 70
               NAME: thread/sql/one_connection
               TYPE: FOREGROUND
     PROCESSLIST_ID: 8
   PROCESSLIST_USER: root
   PROCESSLIST_HOST: localhost
     PROCESSLIST_DB: xhy
PROCESSLIST_COMMAND: Query
   PROCESSLIST_TIME: 2599
  PROCESSLIST_STATE: waiting for handler commit
   PROCESSLIST_INFO: insert into t values(i, i, i)
   PARENT_THREAD_ID: 1
               ROLE: NULL
       INSTRUMENTED: YES
            HISTORY: YES
    CONNECTION_TYPE: Socket
       THREAD_OS_ID: 5094
     RESOURCE_GROUP: USR_default
1 row in set (0.00 sec)

ERROR: 
No query specified

可以看到5094的线程执行的是insert 语句,执行了2599秒
继续使用kill 来杀掉这个线程。
我们先使用 kill query 方式来

mysql> kill query 8;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from performance_schema.threads where THREAD_OS_ID=5094\G;
*************************** 1. row ***************************
          THREAD_ID: 70
               NAME: thread/sql/one_connection
               TYPE: FOREGROUND
     PROCESSLIST_ID: 8
   PROCESSLIST_USER: root
   PROCESSLIST_HOST: localhost
     PROCESSLIST_DB: xhy
PROCESSLIST_COMMAND: Query
   PROCESSLIST_TIME: 2896
  PROCESSLIST_STATE: waiting for handler commit
   PROCESSLIST_INFO: insert into t values(i, i, i)
   PARENT_THREAD_ID: 1
               ROLE: NULL
       INSTRUMENTED: YES
            HISTORY: YES
    CONNECTION_TYPE: Socket
       THREAD_OS_ID: 5094
     RESOURCE_GROUP: USR_default
1 row in set (0.00 sec)

ERROR: 
No query specified

可以看到kill query 8虽然提示执行成功了,但并没有真的kill掉这个线程,因为该线程是执行一个存过,里面有多个语句。
再使用kill 方式

mysql> kill 8;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from performance_schema.threads where THREAD_OS_ID=5094\G;
Empty set (0.00 sec)

ERROR: 
No query specified

可以看到5094的线程已经被杀掉了。

总结

发现mysql主机CPU使用率很高时,可以通过如下步骤来找到top 线程,并可通过kill/kill query方式来应急杀掉top线程。
1)使用 top -H 找到cpu使用率高的线程
2)使用 select * from performance_schema.threads where THREAD_OS_ID={操作系统线程ID}\G; 语句找到该线程执行内容。
3)如果是单条长select 语句可以使用 kill query (PROCESSLIST_ID值)来杀掉该查询语句,kill 方式可能杀掉后又重启。
4)如果是多条语句执行可以使用 kill (PROCESSLIST_ID值)来杀掉该线程,kill query方式杀掉一个语句又会起新的语句等于还是没杀掉高CPU线程。

最后修改时间:2022-08-24 22:27:29
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论