MySQL 中的慢查询日志分析

81 阅读7分钟

慢查询日志

慢查询日志的定义

慢查询日志指的是执行时间超过 long_query_time 几秒且至少需要在 min_examined_row_limit 行的检查下得出的 SQL 语句组成。

值得注意的是,获取初始锁的时间不计入执行时间。mysqld在执行完并且释放所有锁后将一条语句写入慢查询日志,因此日志顺序可能与执行顺序不同。

慢查询日志的作用

查找执行时间较长且因此适合优化的查询。

不过,慢查询日志文件可能很长分析起来可能是一项耗时的任务。为了方便,可以使用 mysqldumpslow 命令来 汇总慢查询日志文件。

mysqldumpslow

关于慢查询日志,需要了解两部分

  • 慢查询日志参数
  • 慢查询日志内容

慢查询日志参数

1. long_query_time

最小值: 0 默认值: 10

该值可以指定为微秒的级别。

image.png

默认情况下,不记录管理语句,也不记录不使用索引进行查找的查询。也就是说查询语句只有使用了索引的查询才会被慢查询记录。 可以使用 log_slow_admin_statementslog_queries_not_using_indexes 去更改。见第 6 条和第 7 条。

2. --slow_query_log

默认情况下,慢查询日志是关闭的。

可以使用指令 --slow_query_log[={0|1}] 显式地指定初始慢查询日志状态。

--slow_query_log 指令在没有参数或参数为 1 时都会启用日志。如果参数为 0,将禁用日志。

3. --slow_query_log_file=file_name

使用 --slow_query_log_file=file_name 可以指定日志文件名。 如果不指定慢查询日志文件的名称,则默认名称为 host_name-slow.log。

4. log_output

若要指定日志输出路径,则使用系统变量 log_output。

除非给定的绝对路径名是不同的目录,否则服务器会在数据目录中创建文件。

还可以指定特定表的日志输出路径。

5. --log-short-format

如果使用该选项,服务器会向慢查询日志写入简要的信息。

6. log_slow_admin_statements 系统变量

log_slow_statements 开启此系统变量,将在慢速查询日志中包含管理语句。

image.png 管理语句包括:

  • ALTER TABLE
  • ANALYZE TABLE
  • CHECK TABLE
  • CREATE INDEX
  • DROP INDEX
  • OPTIMIZE TABLE
  • REPAIR TABLE

7. log_queries_not_using_indexes

image.png

启用 log_queries_not_using_indexes 系统变量,使写入慢查询日志的语句中包含 不使用索引进行行查找的查询

(即使启用了该变量,MySQL 也不会记录由于表的行数少于两行而无法走索引的查询。)

8. log_throttle_queries_not_using_indexes

当记录不使用索引的查询时,慢查询日志可能会快速增长。可以通过设置 log_throttle_queries_not_using_indexes 系统变量来对这些查询设置速率限制。默认情况下,该变量为 0,表示没有限制。该变量大于 0 时,对不使用索引的查询的日志记录施加每分钟限制。

第一个查询会开启一个 60 秒的窗口,在此窗口中服务器会记录达到给定限制的查询,然后拦截额外的查询。如果窗口结束时存在被拦截的查询,服务器会记录一个摘要,显示有多少个查询以及在这些查询中花费的总时间。当服务器记录下一个不使用索引的查询时,下一个 60 秒的窗口开始。

MySQL 按以下顺序使用控制参数来确定是否将查询写入慢查询日志:

  1. 该查询必须不是管理语句,或者 log_slow_admin_statements 已启用。

  2. 该查询必须至少花费几 long_query_time 秒钟,或者 log_queries_not_using_indexes 已启用并且查询不采用任何索引。

  3. 该查询必须至少检查了 min_examined_row_limit 行。

  4. 根据设置不得抑制查询 log_throttle_queries_not_using_indexes

  5. 默认情况下,副本不会将复制查询写入慢查询日志。要更改此设置,启用系统变量 log_slow_replica_statementslog_slow_slave_statements

  6. 需注意的是,如果使用基于行的复制 (binlog_format=ROW),则这些系统变量无效。只有当查询以语句格式记录在二进制日志中时,即当 binlog_format=STATEMENT 设置时,或者当 binlog_format=MIXED 设置并且语句以语句格式记录时,查询才会添加到副本的慢查询日志中。即便是启用了 log_slow_replica_statementslog_slow_slave_statements,以行格式记录的慢查询,在 binlog_format=MIXED 或 binlog_format=ROW 设置时,慢查询也不会添加到副本的慢查询日志中。

慢查询日志内容

启用慢查询日志后,服务器将输出写入 log_output 系统变量指定的任何目标。如果启用日志,服务器将打开日志文件并向其中写入启动消息。FILE但是,除非选择了日志目标,否则不会进一步将查询记录到文件中。如果目标是 NONE,即使启用了慢查询日志,服务器也不会写入任何查询。FILE如果未选择 为输出目标, 则设置日志文件名不会影响日志记录。

如果启用慢查询日志并FILE选择作为输出目标,则写入日志的每个语句前面都有一行以字符开头 #并包含以下字段(所有字段都在一行上):

Query_time: duration

语句执行时间(以秒为单位)。

Lock_time: duration

获取锁的时间(以秒为单位)。

Rows_sent: N

发送到客户端的行数。

Rows_examined:

服务器层检查的行数(不计算存储引擎内部的任何处理)。

启用系统变量会导致服务器 除了刚刚列出的字段之外,log_slow_extra 还将以下额外字段写入输出(输出不受影响)。某些字段描述引用状态变量名称。有关更多信息,请参阅状态变量描述。但是,在慢查询日志中,计数器是每个语句的值,而不是每个会话的累积值。 FILE TABLE

慢查询日志内容
字段 (类型)含义
Query_time:duration语句执行时间(以秒为单位)
Lock_time:duration获取锁的时间(以秒为单位)
Rows_sent:N发送到客户端的行数
Rows_examined服务器层检查的行数(不计算存储引擎内部的任何处理)
Thread_id:ID语句线程标识符
Errno: error_number语句错误号,如果没有发生错误则为 0
Killed: N如果语句终止,则错误号指示原因;如果语句正常终止,则错误号为 0
Bytes_received: NBytes_received语句的值
Bytes_sent: NBytes_sent语句的值
Read_first: NHandler_read_first 语句的值
Read_last: NHandler_read_last 语句的值
Read_key: NHandler_read_key语句的值
Read_next: NHandler_read_next 语句的值
Read_prev: NHandler_read_prev 语句的值
Read_rnd: NHandler_read_rnd语句的值
Read_rnd_next: NHandler_read_rnd_next 语句的值
Sort_merge_passes: NSort_merge_passes 语句的值
Sort_range_count: NSort_range语句的值
Sort_rows: NSort_rows语句的值
Sort_scan_count: NSort_scan语句的值
Created_tmp_disk_tables: NCreated_tmp_disk_tables 语句的值
Created_tmp_tables: NCreated_tmp_tables 语句的值
Start: timestamp语句执行开始时间
End: timestamp语句执行结束时间

给定的慢查询日志文件可能包含包含或不包含通过启用添加的额外字段的混合行 log_slow_extra。日志文件分析器可以通过字段计数确定一行是否包含附加字段。

写入慢查询日志文件的每个语句前面都有一个SET 包含时间戳的语句。

从 MySQL 8.0.14 开始,时间戳指示慢语句开始执行的时间。在 8.0.14 之前,时间戳指示记录慢速语句的时间(在语句完成执行后发生)。

写入慢查询日志的语句中的密码由服务器重写,不会以纯文本形式出现。请参见第 6.1.2.3 节“密码和日志记录”。

从 MySQL 8.0.29 开始,无法解析的语句(例如由于语法错误)不会写入慢查询日志。

MySQL8.0参考手册:dev.mysql.com/doc/refman/…