慢查询日志
慢查询日志包含执行时间超过 long_query_time 秒且至少需要检查 min_examined_row_limit 行的 SQL 语句。慢查询日志可以用来找出执行时间长且可能需要优化的查询。然而,检查慢查询日志可能是一项耗时的任务。为了更方便地进行检查,您可以使用 mysqldumpslow 命令处理慢查询日志文件并对其内容进行总结。
获取初始锁的时间不计入执行时间。mysqld 在语句执行后并释放所有锁之后将其写入慢查询日志,因此日志顺序可能与执行顺序不同。
慢查询日志参数
long_query_time 的最小和默认值分别为 0 和 10。该值可以以微秒为单位进行指定。
默认情况下,不会记录管理语句,也不会记录不使用索引进行查找的查询。可以通过后续描述的 log_slow_admin_statements 和 log_queries_not_using_indexes 来更改此行为。
默认情况下,慢查询日志被禁用。要显式指定初始慢查询日志状态,请使用 –slow_query_log[={0|1}]。不带参数或参数为 1 的情况下,–slow_query_log 启用日志记录。参数为 0 的情况下,此选项禁用日志记录。要指定日志文件名,请使用 –slow_query_log_file=file_name。要指定日志目标,请使用 log_output 系统变量。
如果未为慢查询日志文件指定名称,则默认名称为 host_name-slow.log。服务器将文件创建在数据目录中,除非给出绝对路径名以指定其他目录。
要在运行时禁用或启用慢查询日志,或更改日志文件名称,请使用全局慢查询日志和慢查询日志文件系统变量。将 slow_query_log 设置为 0 可禁用日志,将其设置为 1 可启用日志。设置 slow_query_log_file 可指定日志文件的名称。如果已经打开了一个日志文件,则会关闭它并打开新文件。
如果使用 –log-short-format 选项,服务器将向慢查询日志写入较少的信息。
要在慢查询日志中包含慢管理语句,请启用 log_slow_admin_statements 系统变量。管理语句包括 ALTER TABLE、ANALYZE TABLE、CHECK TABLE、CREATE INDEX、DROP INDEX、OPTIMIZE TABLE 和 REPAIR TABLE。
要在被写入慢查询日志的语句中包含不使用索引进行行查找的查询,请启用 log_queries_not_using_indexes 系统变量。(即使启用了该变量,服务器也不会记录由于表中少于两行而无法从索引中获益的查询。)
当记录不使用索引的查询时,慢查询日志可能会快速增长。可以通过设置 log_throttle_queries_not_using_indexes 系统变量来对这些查询设置速率限制。默认情况下,该变量为 0,表示没有限制。正值会对不使用索引的查询的日志记录施加每分钟限制。第一个这样的查询打开一个 60 秒的窗口,在该窗口内,服务器记录的查询数量不超过给定的限制,然后抑制额外的查询。如果在窗口结束时存在被抑制的查询,则服务器记录一个摘要,指示有多少查询以及在其中花费的总时间。下一个 60 秒的窗口从服务器记录下一个不使用索引的查询开始。
服务器使用以下顺序的控制参数来确定是否将查询写入慢查询日志:
- 查询必须不是管理语句,或者必须启用 log_slow_admin_statements。
- 查询必须至少执行了 long_query_time 秒,或者必须启用 log_queries_not_using_indexes 并且查询在行查找中没有使用索引。
- 查询必须至少检查了 min_examined_row_limit 行。
- 查询不能根据 log_throttle_queries_not_using_indexes 设置被抑制。
log_timestamps 系统变量控制写入慢查询日志文件的消息中的时间戳的时区(以及常规查询日志文件和错误日志)。它不会影响写入日志表的常规查询日志和慢查询日志消息的时区,但是从这些表检索的行可以通过 CONVERT_TZ() 或设置会话 time_zone 系统变量将其从本地系统时区转换为任何所需的时区。
默认情况下,副本不会将复制的查询写入慢查询日志。要更改此设置,可以启用系统变量 log_slow_replica_statements(从 MySQL 8.0.26 开始)或 log_slow_slave_statements(在 MySQL 8.0.26 之前)。请注意,如果正在使用基于行的复制(binlog_format=ROW),这些系统变量不起作用。当以语句格式在二进制日志中记录查询时,即设置 binlog_format=STATEMENT 或设置 binlog_format=MIXED 且语句以语句格式记录时,查询才会被添加到副本的慢查询日志中。当以行格式记录查询时(当设置 binlog_format=MIXED 时),或者当设置 binlog_format=ROW 时记录查询时,即使启用了 log_slow_replica_statements 或 log_slow_slave_statements,也不会将慢查询添加到副本的慢查询日志中。
慢查询日志内容
当慢查询日志被启用时,服务器会将输出写入 log_output 系统变量指定的任何目标。如果启用了日志,服务器会打开日志文件并将启动消息写入其中。但是,除非选择了 FILE 日志目标,否则不会将查询进一步写入文件中。如果目标是 NONE,即使启用了慢查询日志,服务器也不会写入任何查询。如果没有选择 FILE 作为输出目标,设置日志文件名对日志记录没有影响。
如果启用了慢查询日志并选择了 FILE 作为输出目标,每个写入日志的语句前面都有以 # 字符开头的行,并具有以下字段(所有字段都在一行上):
- Query_time: duration
- 语句执行的时间,以秒为单位。
- Lock_time: duration
- 获取锁的时间,以秒为单位。
- Rows_sent: N
- 发送给客户端的行数。
- Rows_examined:
- 服务器层检查的行数(不包括存储引擎内部的任何处理)。
- 启用 log_slow_extra 系统变量(从 MySQL 8.0.14 开始提供)会导致服务器在 FILE 输出中除了刚刚列出的字段之外,还写入以下额外字段(TABLE 输出不受影响)。一些字段描述中引用了状态变量的名称。请参考状态变量的描述以获取更多信息。但是,在慢查询日志中,计数器是每个语句的值,而不是累积的会话值。
- Thread_id: ID
- 语句线程标识符。
- Errno: error_number
- 语句错误号,如果没有错误发生,则为 0。
- Killed: N
- 如果语句被终止,表示终止原因的错误号,如果语句正常终止,则为 0。
- Bytes_received: N
- 语句的 Bytes_received 值。
- Bytes_sent: N
- 语句的 Bytes_sent 值。
- Read_first: N
- 语句的 Handler_read_first 值。
- Read_last: N
- 语句的 Handler_read_last 值。
- Read_key: N
- 语句的 Handler_read_key 值。
- Read_next: N
- 语句的 Handler_read_next 值。
- Read_prev: N
- 语句的 Handler_read_prev 值。
- Read_rnd: N
- 语句的 Handler_read_rnd 值。
- Read_rnd_next: N
- 语句的 Handler_read_rnd_next 值。
- Sort_merge_passes: N
- 语句的 Sort_merge_passes 值。
- Sort_range_count: N
- 语句的 Sort_range 值。
- Sort_rows: N
- 语句的 Sort_rows 值。
- Sort_scan_count: N
- 语句的 Sort_scan 值。
- Created_tmp_disk_tables: N
- 语句的 Created_tmp_disk_tables 值。
- Created_tmp_tables: N
- 语句的 Created_tmp_tables 值。
- Start: timestamp
- 语句的执行开始时间。
- End: timestamp
- 语句的执行结束时间。
一个给定的慢查询日志文件可能包含一些包含额外字段以及一些不包含额外字段的行,这取决于是否启用了 log_slow_extra。日志文件分析器可以通过字段计数来确定一行是否包含额外字段。
每个写入慢查询日志文件的语句前面都有一个包含时间戳的 SET 语句。从 MySQL 8.0.14 开始,时间戳表示慢语句开始执行的时间。在 8.0.14 之前,时间戳表示慢语句被记录的时间(即语句执行完成后记录的时间)。
写入慢查询日志的语句中的密码会被服务器重写,以避免以明文形式出现。
从 MySQL 8.0.29 开始,无法解析的语句(例如由于语法错误)不会被写入慢查询日志。