MySQL 日志简介
总览
MySQL Server 有以下⼏种⽇志,可以记录服务器正在发⽣的活动。
⽇志类型 | ⽇志信息 |
⼀般查询⽇志 (General query log)
| 已建⽴的客⼾端连接和从客⼾端接收到的语句 |
错误⽇志 (Error log)
|
mysqld在启动、运⾏或停⽌时遇到的问题
|
慢查询⽇志 (Slow query log)
|
执⾏时间超过
long_query_time
指定秒数的查询
|
⼆进制⽇志 (Binary log)
|
更改数据的语句(也⽤于主从复制)
|
中继⽇志 (Relay log)
|
从源服务器接收到的数据更改
|
DDL⽇志(metadata log)
|
DDL 语句执⾏的操作
|
回滚⽇志/撤销⽇志(undo log)
|
⽤于事务的回滚操作
|
重做⽇志(redo log)
|
⽤于服务器崩溃恢复
|
- 默认情况下,除 Windows 上的错误⽇志外,不启⽤任何⽇志,Linux下默认开启错误⽇志和⼆进制⽇志
- 通过 FLUSH LOGS 语句刷新⽇志来强制服务器关闭并重新打开⽇志⽂件,也可以使⽤mysqladmin 的 flush-logs 或 refresh 参数,或mysqldump 的 --flush-logs 或 --master-data 选项
⼀般查询日志和慢查询日志的输出形式
在服务器运⾏期间可以控制⼀般查询和慢查询⽇志的禁⽤与开启,也可以更改⽇志⽂件名,⼀般查询⽇志和慢查询⽇志记录的输出⽅式可以指定为⽇志⽂件或 mysql 系统库中的 general_log 和 slow_log 表,也可以两者同时指定。
log_output
系统变量指定⽇志输出的形式,但并不会真正的启⽤⽇志。
log_output
可以有三个值,分别是:
ABLE
(表)、
FILE
(⽂件)、
NONE
(不输出),可以同时指定多个值,并⽤逗号隔开,未指定值时默认是
FILE
,如果列表中存在
NONE
则其他的不⽣效,也就是说
NONE
的优先级最⾼。
- 通过设置 general_log 系统变量的值来控制⼀般查询⽇志的 开启 1 与 禁⽤ 0 ,如果要为⽇志指定⾃定义的路径或⽂件名可以使⽤ general_log_file 系统变量
- 通过设置 slow_query_log 系统变量的值来控制慢查询⽇志的 开启 1 与 禁⽤ 0 ,如果要为⽇志指定⾃定义的路径或⽂件名可以使⽤ slow_query_log_file 系统变量
- 以选项⽂件 /etc/mysql/my.cnf 中的配置为例,将⼀般查询⽇志和慢查询⽇志写⼊⽇志⽂件,并指定⾃定义的⽇志路径
[mysqld]
#⽇志⽂件
log_output=FILE
#开启⼀般查询⽇志
general_log=1
#指定⾃定义的⽂件名
general_log_file=/var/lib/mysql/general.log
#开启慢查询⽇志
slow_query_log=1
#指定⾃定义的⽂件名
slow_query_log_file=/var/lib/mysql/slow_query.log
- 也可以在运⾏ mysql 时修改 log_output 的值,以更改⽇志的输出形式,通过语句控制
set global log_output=[FILE, TABLE, NONE];
set global general_log=0或1;
set global slow_query_log=0或1;
set global general_log_file=自定义文件路径;
set global slow_query_log_file=自定义文件路径;
如果我们选择⽇志记录以表的形式输出,我们可以查看⽇志表的结构,可以使⽤以下语句:
show create table mysql.general_log\G # ⼀般查询⽇志
show create table mysql.slow_log\G # 慢查询⽇志
⼀般查询日志
General query log,⼀般查询⽇志,记录客⼾端连接或断开连接的信息,也会记录从客⼾端接收的
每个SQL语句。如果开启将会产⽣⼤量的内容,⾮常耗费服务器资源,所以默认为关闭(不开启),
要启⽤⼀般查询⽇志可以使⽤:请使⽤
general_log=1,
默认⽇志⽂件名为
host_name
.log
,可以⽤
general_log_file=
file_name
修改。其中日志的文件结构和表结构参数大体一致,我们学习表结构即可,general_log的表结构如下:
Create Table: CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` bigint unsigned NOT NULL,
`server_id` int unsigned NOT NULL,
`command_type` varchar(64) NOT NULL,
`argument` mediumblob NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COMMENT='General log'
其中connection_type 来指⽰⽤于建⽴连接的协议。TCP/IP 表⽰不使⽤SSL建⽴的TCP/IP连接、SSL/TLS 表⽰使⽤SSL建⽴的TCP/IP连接、Socket 表⽰Unix套接字⽂件连接、Named Pipe 表⽰Windows命名管道连接、 Shared Memory 表⽰Windows共享内存连接。
argument 表示表操作的具体SQL语句,不过这部分内容被加密成了一段乱码,如下
这时我们就需要使用 cast 函数进行转化,函数原型如下:
CAST(expression AS target_type)
其中,expression 是要转换的表达式或值,target_type 是目标数据类型。现在我们要将argument转化为我们能看得懂的文字,就需要使用如下代码
cast(argument as char)
- 查询表中的⽇志内容
select date_format(event_time, '%Y-%m-%d %H:%i:%s') as time,
user_host,
thread_id,
server_id,
command_type,
cast(argument as char) as query
from mysql.general_log\G
截取部分信息如下
慢查询日志
- 慢查询⽇志由执⾏时间超过系统变量 long_query_time 指定的秒数(默认为10秒)的 SQL 语句组成,并且检查的⾏数⼤于系统变量 min_examined_row_limit 指定值。被记录的慢查询需要进⾏优化,可以使⽤ mysqldumpslow客⼾端程序对慢⽇志进⾏分析汇总。
- 默认为关闭(不开启),要启⽤慢查询⽇志可以使⽤:请使⽤ slow_query_log=1 .
- 默认⽇志⽂件名为 host_name-slow.log ,可以使⽤ slow_query_log_file=file_name 修改
- 默认情况下,不记录管理语句,也不记录不使⽤索引的查询,要记录不使⽤索引的查询,启⽤ log_queries_not_using_indexes 系统变量。当记录不使⽤索引的查询时,⽇志会快速增⻓,通过设置系统变量 log_throttle_queries_not_using_indexes 限制每分钟写⼊慢查询⽇志同类查询的数量,默认值是0,表⽰⽆限制;要记录管理语句,启⽤ log_slow_admin_statements 系统变量。管理语句包括 ALTER TABLE 、 ANALYZE TABLE 、 CHECK TABLE 、 CREATE INDEX 、 DROP INDEX 、OPTIMIZE TABLE 和 REPAIR TABLE 。
慢查询⽇志表的表结构如下
Create Table: CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
`rows_sent` int NOT NULL,
`rows_examined` int NOT NULL,
`db` varchar(512) NOT NULL,
`last_insert_id` int NOT NULL,
`insert_id` int NOT NULL,
`server_id` int unsigned NOT NULL,
`sql_text` mediumblob NOT NULL,
`thread_id` bigint unsigned NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COMMENT='Slow log'
- start_time:记录SQL语句执行完写slow log的时间。
- user_host:执行SQL语句的用户和主机名。
- query_time:SQL语句的执行时间,不包括锁等待时间。
- lock_time:执行SQL语句前,等待锁的时间。
- rows_sent:SQL语句返回的结果集行数。
- rows_examined:SQL聚集执行时扫描的行数。
- db:执行SQL语句的库名。
- last_insert_id:与插入操作相关的ID。
- insert_id:与插入操作相关的ID。
- server_id:服务器ID。
- sql_text:执行的SQL语句。
- thread_id:执行SQL的线程ID。
错误日志
错误⽇志⼀般会记录mysqld 启动和关闭的次数、诊断消息,以及服务器运⾏期间发⽣的错误和警
告;例如MySQL需要⾃动检查或修复⼀个表,就会在错误⽇志中写⼊⼀条记录。错误⽇志默认使⽤ UTF-8 ( utf8mb3
)编码格式,并使⽤英语⽣成记录。
Windows 的默认错误日志路径
在Windows系统中,mysqld使⽤
--log-error
和
--console
选项来确定默认的错误⽇志⽬标是控制台还是⽂件,规则如下:
- 如果指定了 --console 选项,默认在控制台输出错误⽇志,如果 --console 和 --log-error 同时指定,则 --console 优先级更⾼,并且 --log-error 将失效。
- 如果没有指定 --log-error 或者没有指定具体的⽂件名,默认在数据⽬录中⽣成名为host_name.err 的⽇志⽂件。
- 可以通过指定绝对路径,来更改默认的⽇志位置。
[mysqld]
log-error=D:/log/MySQL/Error/error_log.err # ⾃定义错误⽇志的路径
Unix 和Linux 的默认错误日志路径
在 Unix 和Linux 系统中,mysqld使⽤
--log-error
选项来指定默认错误⽇志⽬标,可以指定控制
台或是⽂件,如果是⽂件,规则如下:
- 如果错误⽇志输出⽬标是控制台,则服务器将 log_error 系统变量设置为 stderr,否则,将以⽂件形式输⼊错误⽇志,并以 log_error 的值为⽂件名。
- 如果显⽰写出 --log-error 但没有指定具体⽂件,则默认路径是数据⽬录中 host_name.err 的⽂件。
- 可以在/etc/mysql/my.cnf 中通过指定绝对路径,来更改默认的⽇志位置。
[mysqld]
log-error=/var/log/mysql/error_log.err # ⾃定义错误⽇志的路径
错误日志中事件的字段
- time :事件时间戳,精度为微秒
- msg :事件消息字符串
- prio :事件优先级,包括 System event - 系统(0)、 Error event - 错误(1)、 Warning event - 警告(2)或 Note/information event - 通知/提⽰事件(3),值越⼩优先级越⾼
- err_code :事件错误代码
- err_symbol :以字符串形式表⽰的事件错误符,例如 'ER_DUP_KEY'
- SQL_state :事件 SQLSTATE 值,与 err_symbol 对应,例如 'ER_DUP_KEY' 对应的 SQLSTATE为23000
- subsystem :事件发⽣的⼦系统。可能的值: InnoDB (InnoDB存储引擎)、 Repl (复制⼦系统)、 Server (其他)
示例如下:
2023-07-27T14:15:59.267828+08:00 1 [System] [MY-011012] [Server] Starting
upgrade of data directory.
2023-07-27T14:15:59.267942+08:00 1 [System] [MY-013576] [InnoDB] InnoDB
initialization has started.
2021-07-27T14:16:11.478109+08:00 1 [System] [MY-013577] [InnoDB] InnoDB
initialization has ended.
每一行日志内容从左到右依次为 time,prio,err_code,subsystem,错误具体详情。
如果使⽤ flush error logs
、flush logs(刷新所有日志)
语句或
mysqladmin flush-logs
(刷新所有日志)命令刷新错误⽇志,服务器会将正在写⼊的任何错误⽇志⽂件关闭并重新打开,如果重新打开时找不到错误日志文件就会重新生成一个新的日志文件。
如果要⼿动重命名错误⽇志⽂件,可以在重命名操作之后执⾏刷新操作,服务器会以原⽂件名⽣成
⼀个新的错误⽇志⽂件,例如⽇志⽂件名为
host_name
.err
,可以按以下步骤操作:
mv host_name.err host_name.err-old # 重命名⽇志⽂件
mysqladmin flush-logs # 刷新操作
mv host_name.err-old backup-directory # 把重命名的⽇志⽂件移动到备份⽬录
二进制日志
二进制⽇志包含数据库更改的"事件",不会记录
SELECT
和
SHOW
,但会记录表的创建操作或
表数据的更改,⼆进制⽇志还包含每个语句更新数据时花费的时间信息,启动⼆进制⽇志,对服务
器性能稍微有些影响。
⼆进制⽇志的作⽤:
- 主从节点数据复制:从节点服务器读取主节点服务器上的⼆进制⽇志⽂件,并根据⼆进制⽇志中记录的事件在从节点上执⾏相同的操作,保证主从节点服务器上数据⼀致,实现数据复制功能。
- 数据恢复:从某个时间点恢复备份数据后,将重新执⾏备份时间点之后记录在⼆进制⽇志中的事件。这些事件使数据库从备份点更新到当前最新状态。
在mysql上查看⼆进制⽇志相关的系统变量
show variables like '%bin%';
- 默认情况下启⽤⼆进制⽇志, log_bin 系统变量为 ON
- 禁⽤⼆进制⽇志,可以指定 --skip-log-bin 或 --disable-log-bin 选项
- 选项 --log-bin=base_name ⽤于指定⼆进制⽇志⽂件的基本名称,如果不指定 --log-bin 选项,默认基本名称为 binlog ,建议为⼆进制⽇志指定⼀个基本名
- ⼆进制⽇志⽂件名是由基本名+数字扩展名组成的,服务器每次创建⼀个新的⽇志⽂件时,数字扩展名都会增加,从⽽保证有序的⽂件系列,发⽣以下事件时,服务器都会在创建⼀个新的⽇志⽂件:1.服务器已启动或重新启动;2.服务器刷新⽇志;3.当前⽇志⽂件的⼤⼩达到 max_binlog_size (单个⽇志⽂件的最⼤字节数,最⼩值 4096 字节,最⼤值和默认值 1GB)
- mysqld还会创建⼀个包含⼆进制⽇志⽂件名的⽇志索引⽂件,默认情况下,这与⼆进制⽇志⽂件具有相同的基本名称,扩展名为 .index . 可以使⽤选项 --log-bin-index=file_name修改索引⽂件名
- ⼆进制⽇志⽂件和索引⽂件的默认位置是数据⽬录//var/lib/mysql。可以使⽤ --log-bin=file_name选项指定⾃定义路径, file_name 格式 = 绝对路径+基本名。 --log-bin 对应的系统变量是 log_bin_basename
配置⽇志输出位置
查看二进制日志
- 使⽤客⼾端⼯具mysqlbinlog查看
mysqlbinlog binlog.000011 > binlog.000011
左边 binlog.000011 为二进制日志文件,右边 binlog.000011 为导出的文件。
- 通过SQL语句查看
show binlog events in 'binlog.000011' from N limit S;
例如,我们使用如下代码
show binlog events in 'binlog.000011' limit 10;
- Log_name: 二进制日志文件名
- Pos: 当前这条日志在文件的起始偏移量
- Event_type: 日志类型
- Server_id: 服务器Id,表明是哪台主机
- End_log_pos: 当前日志在文件中的结束偏移量
- Info: 具体执行的操作
配置日志输出位置
我们可以在/etc/mysql/my.cnf添加如下配置,改变日志的输出位置,使其更规范
# 服务器节点
[mysqld]
# ⼀般查询⽇志和慢查询⽇志记录⽅式为⽂件
log-output=FILE
# 开启⼀般查询⽇志
general-log=1
# ⼀般查询⽇志路径和⽂件名
general_log_file=/var/log/mysql/general.log
# 开启慢查询⽇志
slow-query-log=1
# 慢查询⽇志路径和⽂件名
slow_query_log_file=/var/log/mysql/slow_query.log
# 慢查询⽇志时间限制
long_query_time=10
# 错误⽇志路径和⽂件名
log-error=/var/log/mysql/error.log
# ⼆进制⽇志路径和基本名
log-bin=/var/log/mysql/binlog.log
服务器日志维护
MySQL 服务器可以创建多种不同的⽇志⽂件来帮助我们查看服务器的活动。但是必须定期清理这 些⽂件,以免⽇志占⽤过多的磁盘空间。在启⽤⽇志的情况下,通常希望备份和删除旧的⽇志⽂件,并把⽇志写到新⽂件。
- 默认⼆进制⽇志的过期时间为30天,过期后将⾃动删除,要指定⾃定义过期时间,可以使⽤系统变量 binlog_expire_logs_seconds=N 单位为秒,在下⼀次启动服务器和刷新⽇志时删除过期⽇志⽂件
- 强制使⽤新的⽇志⽂件可以⼿动刷新⽇志,当执⾏ flush logs 语句或 mysqladmin flush-logs 、 mysqladmin refresh 、 mysqldump --flush-logs 、 mysqldump --master-data 命令时,会发⽣⽇志刷新。此外当⼆进制⽇志⽂件⼤⼩达到max_binlog_size 系统变量指定的值时,服务器会⾃动刷新⼆进制⽇志。
- flush logs⽀持可选的修饰符以启⽤个别⽇志的选择性刷新:
flush binary logs # 刷新⼆进制⽇志
flush error logs # 刷新错误⽇志
flush general logs # 刷新⼀般查询⽇志
flush relay logs # 刷新中继⽇志
flush slow logs # 刷新慢查询⽇志
- 刷新⼀般查询⽇志、慢查询⽇志或错误⽇志只是关闭并重新打开⽇志⽂件,如果要备份可以先重命名再执⾏刷新操作,⽐如⼀般查询⽇志、慢查询⽇志或错误⽇志⽂件名分别为: mysql.log 、mysql-slow.log 和 err.log ,可以在命令⾏中使⽤如下⼀系列命令
cd mysql-data-directory #进⼊⽇志⽬录
mv mysql.log mysql.log.old #重命名⼀般查询⽇志
mv mysql-slow.log mysql-slow.log.old #重命名慢查询⽇志
mv err.log err.log.old #重命名错误⽇志
mysqladmin flush-logs #刷新⽇志