mysql故障排查

122 阅读9分钟

参考链接(MySQL 故障诊断:MySQL 占用 CPU 过高问题定位及优化

在 MySQL 中看看当前连接是否有什么异常。

使用 mysql show full processlist 命令用来查看当前线程处理情况

方法一:

mysql [localhost:5727] {msandbox} ((none)) > show full processlist;
+----+----------+-----------+------+---------+------+---------------------+---------------------------------------------+
| Id | User     | Host      | db   | Command | Time | State               | Info                                        |
+----+----------+-----------+------+---------+------+---------------------+---------------------------------------------+
|  3 | msandbox | localhost | test | Query   |    7 | Creating sort index | select * from t_cpu order by rand() limit 1 |
|  4 | msandbox | localhost | NULL | Query   |    0 | starting            | show full processlist                       |
+----+----------+-----------+------+---------+------+---------------------+---------------------------------------------+
2 rows in set (0.00 sec)

方法二:

mysql [localhost:5727] {msandbox} ((none)) > select * from information_schema.processlist;
+----+----------+-----------+------+---------+------+--------------+----------------------------------------------+
| ID | USER     | HOST      | DB   | COMMAND | TIME | STATE        | INFO                                         |
+----+----------+-----------+------+---------+------+--------------+----------------------------------------------+
|  5 | msandbox | localhost | test | Query   |    2 | Sending data | select * from t_cpu order by rand() limit 1  |
|  6 | msandbox | localhost | NULL | Query   |    0 | executing    | select * from information_schema.processlist |
|  4 | msandbox | localhost | NULL | Sleep   | 1401 |              | NULL                                         |
|  3 | msandbox | localhost | test | Sleep   | 1405 |              | NULL                                         |
+----+----------+-----------+------+---------+------+--------------+----------------------------------------------+
4 rows in set (0.00 sec)



参数说明:

  • id:标识位,MySQL 进程 ID,使用 kill id,可以杀掉某一个进程
  • user:当前连接的用户
  • host:当前连接的主机
  • db:连接的数据库
  • command:执行的数据库操作类型
  • sleep:休眠状态
  • Query:查询状态
  • connect:连接状态
  • time:已经执行的时间,单位秒
  • info:已经执行的 SQL
  • state:SQL 执行的状态,结果是 SQL 语句整个执行状态中的一个,其中包含很多状态,我们整理如下表:

MySQL 5.7 官方参考MySQL 8.0 官方参考:

状态含义
After create当线程使用函数创建表(包括内部临时表)最后阶段会出现这个状态,即使由于某些错误未能创建成功,也会标识该状态
altering table服务端正在执行 ALTER TABLE
Analyzing线程正在计算 MyISAM 引擎表键值分布(例如 ANALYZE TABLE)
checking permissions线程正在检查服务端是否有执行语句所需要的的权限
Checking table线程正在执行表的检查工作
cleaning up线程已经处理了一个命令,并准备释放内存并重置某些状态
Closing tables线程正在将表中修改的数据刷新到磁盘,同时正在关闭已经用完的表。是一个能很快完成的动作,如果持续完不成,需要确认磁盘空间是否用满或者磁盘使用的负载很高
converting HEAP to ondisk线程正在将内部临时表从 MEMORY 表转换为磁盘表
copy to tmp table线程正在执行一个 ALTER TABLE 语句。在创建一个新表,然后将老表记录复制到新表之前将是此状态
Copying to group table如果语句具有不同的条件 ORDER BY 和 GROUP BY 标准,则按组对行进行排序并将其复制到临时表
Copying to tmp table服务端正在复制到内存中的临时表
Copying to tmp table on disk服务端正在复制到磁盘上的临时表,临时结果集变的太大(参考 8.4.4 节,MySQL 内部临时表的使用),线程正在将临时表从内存更改为基于磁盘的格式来节省内存
Creating index线程正在执行 MyISAM 表的 ALTER TABLE ... ENABLE KEYS
Creating sort index线程正在处理 SELECT 使用内部临时表
creating table线程正在创建表,包括创建临时表
Creating tmp table线程正在内存中或者磁盘上创建临时表,如果临时表在内存中创建之后转换到磁盘,状态为 Copying to tmp table on disk
committing alter table to storage engine服务端完成 ALTER TABLE 并提交结果
deleting from main table服务端正在执行多表删除的第一部分,仅删除第一个表,保存列和偏移量用于删除其他表
deleting from reference tables服务端正在执行多表删除的第二部分,在其他表中删除匹配的行
discard_or_import_tablespace线程正在执行 ALTER TABLE ... DISCARD TABLESPACE or ALTER TABLE ... IMPORT TABLESPACE 语句
end结束状态,结束之前需要清理 ALTER TABLE, CREATE VIEW, DELETE, INSERT, SELECT, or UPDATE
executing线程正在执行语句
Execution of init_command线程正在执行变量 init_command system 中的语句
freeing items线程执行了一条命令,在此期间完成了一些项目的资源释放,涉及如查询缓存,这个状态之后通常为 cleaning up
FULLTEXT initialization服务端正在准备执行 natural-language 的全文检索
init该状态在 ALTER TABLE, DELETE, INSERT, SELECT, or UPDATE 初始化之前,服务端在该状态下会刷新二进制日志和 InnoDB 日志,清理查询缓存
Killed有发送了一个 KILL 线程的请求,下次终止前会检查 kill 标志位。MySQL 会在每次主循环中检查 kill 标志位,有时该线程并不能立马杀掉会保留短暂时间,如果该线程被其他线程锁定,那么 kill 会在锁释放后生效
logging slow query线程正在往慢日志中写入语句
login连接线程的初始状态,直到客户端成功完成验证
manage keys服务端开启或者关闭表的索引
Opening tables线程正在打开表,这应该是一个很快的过程,除非有些事情组织了打开表。例如 ALTER TABLE or a LOCK TABLE 会在结束前阻止打开表操作。再就是有必要检查 table_open_cache 参数的值设置是否足够大。
optimizing服务端正在对查询进行初始化优化
preparing查询优化状态
Purging old relay logs线程正在删除不需要的中继日志
query end处理完查询,在 freeing items 之前的状态
Receiving from client服务端正在读取客户端的包,该状态在 5.7.8 叫 Reading from net
Removing duplicates查询正在使用 SELECT DISTINCT,这个过程 MySQL 在早期阶段无法完成,因此需要一个额外的阶段在把结果返回给客户端前需要删除重复行
removing tmp table线程在执行完 SELECT 后删除中间临时表,如果没有使用临时表,无该状态
rename重命名表
rename result table线程正在执行 ALTER TABLE 语句,创建一个新表,重命名新表替换老表
Reopen tables线程给表加锁,但是发现在获取表后发现表结构发生了变化。当释放锁,关闭表之后尝试重新打开表
Repair by sorting使用排序创建索引修复代码
preparing for alter table服务端正准备就地执行 ALTER TABLE
Repair done线程已完成对 MyISAM 表的多线程修复
Repair with keycache创建索引缓存修复代码,比 Repair by sorting 慢的多
Rolling back线程在回滚事务
Saving state对于 MyISAM 表的修复和分析操作,线程将新表保存到.MYI 文件头,状态包含行数,AUTO_INCREMENT 计数器,键值分布之类的信息
Searching rows for update线程正在执行第一阶段查询未更新的数据,如果更新了索引所在行就会执行有该状态
Sending data线程正在读取和处理 SELECT 的行记录,发送给客户端,由于在这个状态下的操作会执行大量的磁盘访问(读),因此它通常是查询生命周期最长的状态。
Sending to client服务端正在给客户端发送包,在 5.7.8 该状态叫 Writing to net
setup线程开始执行 ALTER TABLE 操作
Sorting for group线程正在做排序来满足 GROUP BY
Sorting for order线程正在做排序来满足 ORDER BY
Sorting index线程正在做索引页优化来使得 MyISAM 表优化操作期间有更高效的访问
Sorting result对于一个 SELECT 语句,类似不使用临时表的 Creating sort index
starting语句执行的第一个状态
statistics服务端正在计算统计信息对一个查询创建执行计划,如果持续很长时间,服务端可能正在执行其他的操作
System lock线程调用了 mysqllocktables(),并且一直未更新状态,这个状态非常常见,可能有很多原因造成。
update线程正准备执行更新操作
Updating线程正在检索要更新的行并且更新行
updating main table服务端正在执行多表更新的第一部分,仅更新第一个表,保存列和偏移量用于更新其他表
updating reference tables服务端正在执行多表更新的第二部分,在其他表中更新匹配的行
User lock线程正在使用 GET_LOCK()请求或等待一个意向锁,对于 SHOW PROFILE 这个状态意味着线程请求锁(但是不等锁)
User sleep线程正在调用 SLEEP()
Waiting for commit lockFLUSH TABLES WITH READ LOCK 正在等待一个提交锁
Waiting for global read lockFLUSH TABLES WITH READ LOCK 正在等待全局读锁或者设置系统全局变量 read_only
Waiting for tables线程得到一个表结构变化的通知,需要重新打开表获取新的表结构,该线程需要等待其他线程关闭该表。这个通知发生在另外的线程执行了 FLUSH TABLES,ALTER TABLE,RENAME TABLE,REPAIR TABLE,ANALYZE TABLE or OPTIMIZE TABLE
Waiting for table flush线程正在执行 FLUSH TABLES,正在等待其他线程关闭他们的表,或者是线程得到一个表结构变化的通知,需要重新打开表获取新的表结构,该线程需要等待其他线程关闭该表。这个通知发生在另外的线程执行了 FLUSH TABLES,ALTER TABLE,RENAME TABLE,REPAIR TABLE,ANALYZE TABLE or OPTIMIZE TABLE
Waiting for lock_type lock服务端正在等待 THR_LOCK 锁,或者是元数据锁定子系统的锁,其中 lock_type 是锁的类型,等待 THR_LOCK 锁(Waiting for table level lock),等待元数据锁(Waiting for event metadata lock、Waiting for global read lock、Waiting for schema metadata lock、Waiting for stored function metadata lock、Waiting for stored procedure metadata lock、Waiting for table metadata lock、Waiting for trigger metadata lock)
Waiting on cond线程正在等待条件变为 true 的状态,没有具体可用的状态信息
Writing to net服务端正在网络中写包,在 5.7.8 中该状态叫 Sending to client

通过结果我们可以大致看看如下的情况:

  • 是否有大量的未执行查询语句
  • 是否有正在执行的 DML 语句
  • 是否有执行了很长时间的 DDL 语句
  • 是否有锁等情况

查看mysql的qps

通过\s命令 查看mysql服务器端信息,获取qps 如下图 685

(关于qps如何计算 参考链接 技术分享 | 如何计算 MySQL 的 QPS/TPS)

image.png

慢sql分析

慢sql优化(转载)