MySQL日志详细说明

时间:2024-01-21 16:14:15

这片博文我们会详细说明MySQL本身的日志,不包含重做日志和undo日志(这两个日志是innodb存储引擎的日志)。

MySQL本身的日志有以下几种(MySQL5.7版本):

  • 错误日志
  • 慢查询日志
  • 通用日志
  • 二进制日志

错误日志

默认情况下,错误日志是无法被禁止;错误日志的位置及日志名使用log_error参数指定,若是没有指定,则默认错误日志名为hostname.err(错误日志是以.err为后缀的)。yum安装的MySQL错误日志默认路径是在/var/log/mysqld.log下的!

在MySQL的官方文档中还介绍了可以把MySQL的错误日志写入到系统日志中,但是如果这样的话,查看会不太方便,不再细说给出官方链接: https://dev.mysql.com/doc/refman/5.7/en/error-log-syslog.html

log_error_verbosity:系统变量控制服务器记录错误日志的详细性,以便将错误,警告和注释信息写入错误日志。其有三个取值,1:仅限错误;2:错误和警告;3:错误,警告和注释,默认数值是3。如果该值大于2,则服务器将记录中止的连接以及新连接尝试的拒绝访问错误。

log_timestamps:系统变量控制写入错误日志(以及常规查询日志和慢速查询日志文件)的消息中时间戳的时区。允许的值为UTC(默认值)和系统(本地系统时区)。

刷新错误日志和重命名:

如果使用flush error logs、flush logs或mysqladmin flush-logs刷新日志,服务器将关闭并重新打开它正在写入的任何错误日志文件。要重命名错误日志文件,请在刷新之前手动执行此操作。刷新日志,然后打开一个具有原始文件名的新文件。

[root@mgt01 mysql]# ll -h mgt01.err                      #当前错误日志
-rw-r----- mysql mysql 2.1M Jan : mgt01.err
[root@mgt01 mysql]# mv mgt01.err mgt01.bak #更改当前错误日志的名字
[root@mgt01 mysql]# mysqladmin flush-logs #执行刷新日志操作,就会重新打开一个以原错误日志名命名的新文件。
[root@mgt01 mysql]# ll -h mgt01.err mgt01.bak
-rw-r----- mysql mysql 2.1M Jan : mgt01.bak
-rw-r----- mysql mysql Jan : mgt01.err

慢查询日志

慢查询日志由执行时间超过long_query_time指定的秒数的SQL语句组成,并且要求至少检查min_examined_row_limit行。慢速查询日志可用于查找执行时间较长的查询,因此是优化的候选查询。

开启慢查询日志,可以把sql语句执行时间较长的语句写入慢查询日志中,以便查看。

慢查询日志的参数:

在MySQL默认情况下,禁用慢查询日志。若开启慢查询日志可以使用slow_query_log参数,把其设置为1或on。

使用slow_query_log_file指定慢查询日志的文件格式,文件名,文件位置。默认文件在数据库目录下面的,文件名为host-name-slow.log。

long_query_time: 设置慢查询日志的时间限制,默认值是10s,最小值是0.该值可以指定为微妙的分辨率。(MySQL5.7版本)

默认情况下,不记录管理语句,也不记录不使用索引进行查找的语句。

要在慢查询日志中记录管理语句,则启用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参数,这个参数设定每分钟记录到日志的未使用索引的语句数目,超过这个数目后只记录语句数量和花费的总时间。

log_slow_slave_statements:记录从库上的慢查询语句。

log_output: 参数指定慢查询日志输出到文件或者记录在数据库的表中。

一个实例如下:

slow_query_log=ON
long_query_time=
slow_query_log_file= #不指定,默认是在当前数据库目录下面,以当前主机名命名的hostname-slow.log语句。
log_output=FILE
log_queries_not_using_indexes
mysql> select sleep(5);
+----------+
| sleep(5) |
+----------+
| 0 |
+----------+
1 row in set (5.00 sec) [root@mgt01 mysql]# mysqldumpslow mgt01-slow.log #查看慢查询日志 Reading mysql slow query log from mgt01-slow.log
Count: 1 Time=5.00s (5s) Lock=0.00s (0s) Rows=1.0 (1), root[root]@localhost
select sleep(N)
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]

Parse and summarize the MySQL slow query log. Options are

  --verbose    verbose
--debug debug
--help write this text to standard output -v verbose
-d debug
-s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default
al: average lock time
ar: average rows sent
at: average query time
c: count
l: lock time
r: rows sent
t: query time
-r reverse the sort order (largest last instead of first)
-t NUM just show the top n queries
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time

mysqldumpslow的选项

上面的实例时把慢查询日志写入了文件,下面修改log_output值为table,把慢查询日志写入到表中。

log_output=TABLE

#然后再mysql数据库下面生成slow_log表。
mysql> desc slow_log;
+----------------+---------------------+------+-----+----------------------+--------------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+----------------------+--------------------------------+
| start_time | timestamp(6) | NO | | CURRENT_TIMESTAMP(6) | on update CURRENT_TIMESTAMP(6) |
| user_host | mediumtext | NO | | NULL | |
| query_time | time(6) | NO | | NULL | |
| lock_time | time(6) | NO | | NULL | |
| rows_sent | int(11) | NO | | NULL | |
| rows_examined | int(11) | NO | | NULL | |
| db | varchar(512) | NO | | NULL | |
| last_insert_id | int(11) | NO | | NULL | |
| insert_id | int(11) | NO | | NULL | |
| server_id | int(10) unsigned | NO | | NULL | |
| sql_text | mediumblob | NO | | NULL | |
| thread_id | bigint(21) unsigned | NO | | NULL | |
+----------------+---------------------+------+-----+----------------------+--------------------------------+
12 rows in set (0.00 sec) mysql>

在查看慢查询日志的时候,除了使用自带的mysqldumpslow工具外,还可以使用percona的pt-query-digest工具。

常规查询日志

The general query log is a general record of what mysqld is doing. The server writes information to this log when clients connect or disconnect,
and it logs each SQL statement received from clients. The general query log can be very useful when you suspect an error in a client and want
to know exactly what the client sent to mysqld.
#常规查询日志是mysqld所做工作的常规记录。当客户端连接或断开连接时,服务器将信息写入此日志,并记录从客户端接收的每个SQL语句。当您怀疑客户机中存在错误并想确切知道客户
#机发送给mysqld的内容时,常规查询日志非常有用。

常规查询日志记录的内容比较详细,并且会记录执行的每条语句,因此常用于审计的时候使用。开启常规查询语句,对数据库的性能会有一定的影响。默认是关闭的。

general_log: 用于开启常规查询日志,当为0时,关闭常规查询日志。

general_log_file: 用于指定常规查询日志的文件名,文件位置。默认文件名为hostname.log.

log_output: 指定日志输出到文件或者表中。和上面的一样。

mysql> set global general_log=ON;            #开启常规查询日志(常规查询日志可以动态修改)
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like "log_output"; #设置常规查询日志输出到表中
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | TABLE |
+---------------+-------+
1 row in set (0.01 sec)
mysql> use mysql; #会在mysql下面生成general_log表。
Database changed
mysql> select * from general_log;

可以关闭当前会话的常规查询日志如下:

mysql> set sql_log_off=ON;
Query OK, 0 rows affected (0.01 sec)

二进制日志

二进制日志包含描述数据库更改(如表创建操作或表数据更改)的“事件”。二进制日志主要有两个功能:

对于select语句,和show语句,因为不修改数据库中的数据,因此不会记录到二进制日志中;若是想要记录这种不修改数据的语句,可以使用常规查询日志。

与二进制日志有关的参数:

log-bin=    
#MySQL默认不起用二进制日志,这个参数指定二进制的位置,文件名。默认是以主机名命名的(强烈不推荐使用)。使用主机名命名的二进制日志,在迁移到别的主机时会报错。
#二进制文件名以filename.number的形式存在,number的格式是从00001开始的6位数,依次递增。还会生成一个filename.index文件,这个文件存储所有二进制日志文件名的清单。 log_bin_index= #指定上面提到的二进制日志索引文件名。这个文件不需要手动编辑,可以直接默认即可! max_binlog_size: 设置二进制的最大大小,超出这个值时,二进制日志会自动轮换下一个。默认是1G。 binlog_cache_szie:  在事务没有提交的时候使用的缓冲大小(基于会话的),如果缓存大于这个数值则会使用临时文件。可以使用show global status来查看使用临时文件的次数。
             默认是32KB。 mysql> show global status like 'binlog_cache_%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Binlog_cache_disk_use | 0     | #使用临时文件的次数
| Binlog_cache_use      | 0     | #缓冲使用的次数。
+-----------------------+-------+
2 rows in set (0.02 sec) mysql> max_binlog_cache_size: (默认为4GB,也是最大值)可用于限制用于缓存多语句事务的总大小。如果事务大于这个字节数,它将失败并回滚。最小值为4096。 binlog_error_action:如果服务器无法写入二进制日志、刷新二进制日志文件或将二进制日志同步到磁盘,则复制主服务器上的二进制日志可能会不一致,复制从服务器可能会失去与
            主服务器的同步。binlog_error_action系统变量控制在二进制日志遇到此类错误时采取的操作。
   默认设置是abort_server: ABORT_SERVER使服务器暂停二进制日志记录并关闭。此时,您可以识别并更正错误原因。重新启动时,恢复将按意外服务器暂停的情况继续进行.
ignore_error:提供与旧版本MySQL向后兼容。使用此设置,服务器继续正在进行的事务并记录错误,然后暂停二进制日志记录,但继续执行更新。要恢复二进制日志记录,必须重启服务器。
binlog_format:指定二进制日志的格式,有三种选择:
  STATEMENT: 基于语句,把数据库执行的每条语句记录下来。
ROW:   基于行的,主服务器把事件写入二进制日志,以指示各个表行的影响方式。线上标配一般是RC+ROW.
  mixed: 混合日志记录,对于混合日志记录。默认情况下使用基于语句的日志记录,但在某些情况下,日志记录模式会自动切换到基于行的记录。使用混合记录时,
        服务器会在以下条件时,使用基于行的记录。https://dev.mysql.com/doc/refman/5.7/en/binary-log-mixed.html
binlog-row-event-max-size: 在使用基于行的格式时,二进制日志文件中记录的是事件,这个参数表示事件的最大大小。这个value必须是256的倍数,默认是8192. expire_logs_days: 表示二进制的保留时间,超过这个时间的二进制会被自动删除。单位是天,数值类型为整型。
MySQL提供一个sync_binlog参数来控制数据库的binlog刷到磁盘上去。

默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。

如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。但是binlog虽然是顺序IO,但是设置sync_binlog=1,多个事务同时提交,同样很大的影响MySQL和IO性能。虽然可以通过group commit的补丁缓解,但是刷新的频率过高对IO的影响也非常大。对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。

所以很多MySQL DBA设置的sync_binlog并不是最安全的1,而是100或者是0。这样牺牲一定的一致性,可以获得更高的并发和性能。

sync_binlog参数设置

上面说明了与二进制有关的一些参数,下面我们来说明二进制的一些管理以及二进制内容的格式。

首先开启二进制日志,如下:

log-bin=/data/mysql/test-bin
binlog_format=ROW

然后查看二进制日志文件

[root@mgt02 mysql]# ll  test-bin.*
-rw-r----- mysql mysql Dec : test-bin.000001 #二进制日志文件
-rw-r----- mysql mysql Dec : test-bin.index #二进制日志索引文件
[root@mgt02 mysql]# cat test-bin.index #目前索引文件中,只有一个当前的日志文件
/data/mysql/test-bin.000001
[root@mgt02 mysql]# mysqlbinlog test-bin.000001 #查看二进制日志文件可以使用mysqlbinlog命令,因为这里不是介绍这个命令,就不说明这个命令的具体用法
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#181209 21:56:11 server id 15  end_log_pos 123 CRC32 0x1a2a822b     Start: binlog v 4, server v 5.7.23-log created 181209 21:56:11 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
+x4NXA8PAAAAdwAAAHsAAAABAAQANS43LjIzLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD7Hg1cEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
ASuCKho=
'/*!*/;
# at 123
#181209 21:56:11 server id 15  end_log_pos 154 CRC32 0x44f5bfa4     Previous-GTIDs
# [empty]
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

二进制日志的结构和内容

前面我们提到过二进制中存储的是事件,那么这些事件该如何查看呢?

mysql> show binlog events;          #查看当前活跃的二进制日志中的事件。
+-----------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-----------------+-----+----------------+-----------+-------------+---------------------------------------+
| test-bin. | | Format_desc | | | Server ver: 5.7.-log, Binlog ver: |
| test-bin. | | Previous_gtids | | | |
+-----------------+-----+----------------+-----------+-------------+---------------------------------------+
rows in set (0.00 sec) #Log_name: 表示的是当前查看的二进制日志的名字,注意若想查看指定的二进制日志文件大小,则在后面加上in "binlog-filename"即可!
#Pos: 表示当前事件在二进制日志中的位置点,与后面的End_log_pos对应。
#Event_type:表示事件类型,上面的两个分别表示格式描述事件和前面的表示的gtid号。
#Server_id: 表示的是当前服务器的server_id.
#info: 表示事件信息的可读文本。

前面说过,二进制日志并不是一个单独的文件,而是由一系列易于管理的文件组成的,二进制日志包括一组存储实际内容的二进制日志文件和一个用来跟踪二进制日志文件存储位置的二进制日志索引文件。

有一个二进制日志文件是活动二进制日志文件,即当前正在被写入的文件。

每个二进制日志文件都是以格式描述事件开始,以日志轮换事件结束。格式描述事件包括产生该文件的服务器版本号,服务器以及二进制日志信息等。日志轮换事件包含下一个二进制日志文件的名称,告知二进制日志继续写入哪个文件。

每个二进制日志文件中有多个二进制日志事件,各个事件之间相互独立。同时也是构成二进制日志的基本单位。格式描述符事件还有一个标记,标记二进制日志文件是否正常关闭,如果正在写入二进制日志文件,则设置该标记;如果文件关闭,则清除标记。若服务器非正常关机,则二进制日志不是以日志轮换事件结束。

二进制日志文件管理

在主从结构中:

reset  master: 删除了所有二进制日志文件并清空了二进制日志索引文件。

reset slave: 删除了复制用的所有文件,重新开始;使用之前需要先stop slave!

在服务器上若想删除二进制日志可以执行如下命令:

purge binary logs to "binlog-filename": 删除给定文件之前的所有文件

purge binary logs before “datetime”:删除给定时间之前的所有文件。