### 5.4.5 慢查询日志

[](<>)[](<>)

慢查询日志由占用超过[`long_query_time`](server-system-variables.html#sysvar_long_query_time)秒执行并且至少需要[`min_examined_row_limit`](server-system-variables.html#sysvar_min_examined_row_limit)要检查的行。慢查询日志可用于查找需要很长时间执行的查询，因此是优化的候选者。但是，检查长而缓慢的查询日志可能是一项耗时的任务。为了使这更容易，您可以使用[**mysqldumpslow**](mysqldumpslow.html)命令来处理慢查询日志文件并总结其内容。看[第 4.6.10 节，“mysqldumpslow - 总结慢查询日志文件”](mysqldumpslow.html).

获取初始锁的时间不计入执行时间。[**mysqld**](mysqld.html)在慢查询日志执行完毕并且释放所有锁之后，将一条语句写入慢查询日志，因此日志顺序可能与执行顺序不同。

-   [慢查询日志参数](slow-query-log.html#slow-query-log-parameters)

-   [慢查询日志内容](slow-query-log.html#slow-query-log-contents)

#### 慢查询日志参数

的最小值和默认值[`long_query_time`](server-system-variables.html#sysvar_long_query_time)分别为 0 和 10。该值可以指定为微秒的分辨率。

默认情况下，不会记录管理语句，也不会记录不使用索引进行查找的查询。可以使用更改此行为[`log_slow_admin_statements`](server-system-variables.html#sysvar_log_slow_admin_statements)和[`log_queries_not_using_indexes`](server-system-variables.html#sysvar_log_queries_not_using_indexes)，如后所述。

默认情况下，慢查询日志是关闭的。要显式指定初始慢查询日志状态，请使用[`--slow_query_log[={0|1}]`](server-system-variables.html#sysvar_slow_query_log).没有参数或参数为 1，[`--slow_query_log`](server-system-variables.html#sysvar_slow_query_log)启用日志。如果参数为 0，此选项将禁用日志。要指定日志文件名，请使用[`--slow_query_log_file=*`文件名`*`](server-system-variables.html#sysvar_slow_query_log_file).要指定日志目标，请使用[`日志输出`](server-system-variables.html#sysvar_log_output)系统变量（如中所述[第 5.4.1 节，“选择通用查询日志和慢查询日志输出目标”](log-destinations.html)）。

笔记

如果您指定`桌子`记录目的地，见[日志表和“打开的文件太多”错误](log-destinations.html#log-destinations-tables-open-files).

如果不为慢查询日志文件指定名称，则默认名称为`*`主机名`*-slow.log`.服务器在数据目录中创建文件，除非给出绝对路径名来指定不同的目录。

要在运行时禁用或启用慢查询日志或更改日志文件名，请使用全局[`慢查询日志`](server-system-variables.html#sysvar_slow_query_log)和[`慢查询日志文件`](server-system-variables.html#sysvar_slow_query_log_file)系统变量。放[`慢查询日志`](server-system-variables.html#sysvar_slow_query_log)为 0 以禁用日志或为 1 以启用它。放[`慢查询日志文件`](server-system-variables.html#sysvar_slow_query_log_file)指定日志文件的名称。如果日志文件已打开，则将其关闭并打开新文件。

如果您使用[`--日志短格式`](server-options.html#option_mysqld_log-short-format)选项。

要在慢查询日志中包含慢管理语句，请启用[`log_slow_admin_statements`](server-system-variables.html#sysvar_log_slow_admin_statements)系统变量。行政声明包括[`更改表`](alter-table.html),[`分析表`](analyze-table.html),[`检查表`](check-table.html),[`创建索引`](create-index.html),[`删除索引`](drop-index.html),[`优化表`](optimize-table.html)， 和[`维修台`](repair-table.html).

要在写入慢查询日志的语句中包含不使用索引进行行查找的查询，请启用[`log_queries_not_using_indexes`](server-system-variables.html#sysvar_log_queries_not_using_indexes)系统变量。（即使启用了该变量，服务器也不会记录由于表少于两行而无法从索引的存在中受益的查询。）

当记录不使用索引的查询时，慢查询日志可能会快速增长。可以通过设置[`log_throttle_queries_not_using_indexes`](server-system-variables.html#sysvar_log_throttle_queries_not_using_indexes)系统变量。默认情况下，此变量为 0，表示没有限制。正值对不使用索引的查询的日志记录施加了每分钟的限制。第一个这样的查询会打开一个 60 秒的窗口，在该窗口中服务器将查询记录到给定的限制，然后抑制其他查询。如果在窗口结束时有被抑制的查询，服务器会记录一个摘要，指示有多少查询以及在这些查询中花费的总时间。当服务器记录下一个不使用索引的查询时，接下来的 60 秒窗口开始。

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

1.  查询不能是行政声明，或者[`log_slow_admin_statements`](server-system-variables.html#sysvar_log_slow_admin_statements)必须启用。

2.  查询必须至少占用[`long_query_time`](server-system-variables.html#sysvar_long_query_time)秒，或[`log_queries_not_using_indexes`](server-system-variables.html#sysvar_log_queries_not_using_indexes)必须启用并且查询不使用索引进行行查找。

3.  查询必须至少检查过[`min_examined_row_limit`](server-system-variables.html#sysvar_min_examined_row_limit)行。

4.  查询不得根据[`log_throttle_queries_not_using_indexes`](server-system-variables.html#sysvar_log_throttle_queries_not_using_indexes)环境。

    这[`日志时间戳`](server-system-variables.html#sysvar_log_timestamps)系统变量控制写入慢查询日志文件（以及一般查询日志文件和错误日志）的消息中时间戳的时区。它不影响写入日志表的一般查询日志和慢查询日志消息的时区，但是从这些表中检索到的行可以从本地系统时区转换为任何所需的时区[`转换_TZ()`](date-and-time-functions.html#function_convert-tz)或通过设置会话[`时区`](server-system-variables.html#sysvar_time_zone)系统变量。

    默认情况下，副本不会将复制的查询写入慢查询日志。要更改此设置，请启用系统变量[`log_slow_replica_statements`](replication-options-replica.html#sysvar_log_slow_replica_statements)（来自 MySQL 8.0.26）或[`log_slow_slave_statements`](replication-options-replica.html#sysvar_log_slow_slave_statements)（在 MySQL 8.0.26 之前）。请注意，如果正在使用基于行的复制 ([`binlog_format=行`](replication-options-binary-log.html#sysvar_binlog_format))，这些系统变量没有影响。只有在二进制日志中以语句格式记录查询时，才会将查询添加到副本的慢查询日志中，即当[`binlog_format=声明`](replication-options-binary-log.html#sysvar_binlog_format)被设置，或者当[`binlog_format=混合`](replication-options-binary-log.html#sysvar_binlog_format)设置，并且以语句格式记录语句。以行格式记录的慢查询[`binlog_format=混合`](replication-options-binary-log.html#sysvar_binlog_format)已设置，或者在何时记录[`binlog_format=行`](replication-options-binary-log.html#sysvar_binlog_format)已设置，不会添加到副本的慢查询日志中，即使[`log_slow_replica_statements`](replication-options-replica.html#sysvar_log_slow_replica_statements)要么[`log_slow_slave_statements`](replication-options-replica.html#sysvar_log_slow_slave_statements)已启用。

#### 慢查询日志内容

启用慢查询日志后，服务器将输出写入由[`日志输出`](server-system-variables.html#sysvar_log_output)系统变量。如果启用日志，服务器将打开日志文件并将启动消息写入其中。但是，不会进一步记录对文件的查询，除非`文件`选择日志目的地。如果目的地是`没有`，即使启用了慢查询日志，服务器也不会写入任何查询。设置日志文件名对日志记录没有影响，如果`文件`未选择作为输出目的地。

如果启用了慢查询日志并且`文件`被选为输出目标时，写入日志的每个语句前面都有一行，该行以`#`字符并具有以下字段（所有字段都在一行上）：

-   `查询时间：*`期间`*`

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

-   `锁定时间：*`期间`*`

    获取锁的时间（以秒为单位）。

-   `已发送的行数：*`ñ`*`

    发送到客户端的行数。

-   ```已检查的行数：*``*```

    服务器层检查的行数（不包括存储引擎内部的任何处理）。

    启用[`log_slow_extra`](server-system-variables.html#sysvar_log_slow_extra)系统变量（自 MySQL 8.0.14 起可用）导致服务器将以下额外字段写入`文件`除了刚刚列出的输出（`桌子`输出不受影响）。一些字段描述引用状态变量名称。有关更多信息，请参阅状态变量描述。但是，在慢查询日志中，计数器是每个语句的值，而不是每个会话的累积值。

-   `线程 ID：*`ID`*`

    语句线程标识符。

-   `错误：*`错误编号`*`

    语句错误号，如果没有发生错误，则为 0。

-   `被杀：*`ñ`*`

    如果语句被终止，则错误号指示原因，如果语句正常终止，则为 0。

-   `Bytes_received: *`ñ`*`

    这[`Bytes_received`](server-status-variables.html#statvar_Bytes_received)声明的价值。

-   `字节发送：*`ñ`*`

    这[`Bytes_sent`](server-status-variables.html#statvar_Bytes_sent)声明的价值。

-   `读第一：*`ñ`*`

    这[`Handler_read_first`](server-status-variables.html#statvar_Handler_read_first)声明的价值。

-   `阅读最后一个：*`ñ`*`

    这[`Handler_read_last`](server-status-variables.html#statvar_Handler_read_last)声明的价值。

-   `读键：*`ñ`*`

    这[`Handler_read_key`](server-status-variables.html#statvar_Handler_read_key)声明的价值。

-   `阅读下一个：*`ñ`*`

    这[`Handler_read_next`](server-status-variables.html#statvar_Handler_read_next)声明的价值。

-   `Read_prev: *`ñ`*`

    这[`Handler_read_prev`](server-status-variables.html#statvar_Handler_read_prev)声明的价值。

-   `读取_rnd：*`ñ`*`

    这[`Handler_read_rnd`](server-status-variables.html#statvar_Handler_read_rnd)声明的价值。

-   `Read_rnd_next: *`ñ`*`

    这[`Handler_read_rnd_next`](server-status-variables.html#statvar_Handler_read_rnd_next)声明的价值。

-   `Sort_merge_passes: *`ñ`*`

    这[`Sort_merge_passes`](server-status-variables.html#statvar_Sort_merge_passes)声明的价值。

-   `排序范围计数：*`ñ`*`

    这[`排序范围`](server-status-variables.html#statvar_Sort_range)声明的价值。

-   `排序行数：*`ñ`*`

    这[`排序行`](server-status-variables.html#statvar_Sort_rows)声明的价值。

-   `排序扫描计数：*`ñ`*`

    这[`排序扫描`](server-status-variables.html#statvar_Sort_scan)声明的价值。

-   `Created_tmp_disk_tables: *`ñ`*`

    这[`Created_tmp_disk_tables`](server-status-variables.html#statvar_Created_tmp_disk_tables)声明的价值。

-   `Created_tmp_tables: *`ñ`*`

    这[`Created_tmp_tables`](server-status-variables.html#statvar_Created_tmp_tables)声明的价值。

-   `开始： *`时间戳`*`

    语句执行开始时间。

-   `结尾： *`时间戳`*`

    语句执行结束时间。

    给定的慢查询日志文件可能包含混合行，其中包含或不包含通过启用添加的额外字段[`log_slow_extra`](server-system-variables.html#sysvar_log_slow_extra).日志文件分析器可以通过字段计数确定一行是否包含附加字段。

    写入慢查询日志文件的每条语句前面都有一个[`放`](set-variable.html)包含时间戳的语句。从 MySQL 8.0.14 开始，时间戳指示慢语句何时开始执行。在 8.0.14 之前，时间戳指示记录慢速语句的时间（在语句完成执行后发生）。

    写入慢查询日志的语句中的密码由服务器重写，不会以纯文本形式出现。看[第 6.1.2.3 节，“密码和日志记录”](password-logging.html).

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