红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 专栏
  3. MySQL学习笔记
  4. 正文

MySQL 从入门到精通 15:日志

2025年8月7日 7点热度 0人点赞 0条评论

错误日志

默认开启,默认存放目录 /var/log/mysqld.log。

可以通过系统变量查看错误日志位置:

mysql> show variables like '%log_error%';
+----------------------------+----------------------------------------+
| Variable_name              | Value                                  |
+----------------------------+----------------------------------------+
| binlog_error_action        | ABORT_SERVER                           |
| log_error                  | /var/log/mysql/mysqld.log              |
| log_error_services         | log_filter_internal; log_sink_internal |
| log_error_suppression_list |                                        |
| log_error_verbosity        | 2                                      |
+----------------------------+----------------------------------------+

查看错误日志:

sudo tail -n 50 /var/log/mysql/mysqld.log
2025-07-16T13:17:58.550014Z 0 [System] [MY-010116] [Server] /usr/libexec/mysqld (mysqld 8.0.41) starting as process 8295
2025-07-16T13:17:58.562308Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2025-07-16T13:17:58.745581Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2025-07-16T13:17:59.048626Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
...

二进制日志

记录所有的 DDL 语句和 DML 语句,但不包含数据查询(SELECT,SHOW)语句。

作用:

  • 灾难时数据恢复

  • MySQL 的主从复制

在 MySQL 8 中,二进制日志默认开启,相关变量:

mysql> show variables like '%log_bin%';
+---------------------------------+-----------------------------+
| Variable_name                   | Value                       |
+---------------------------------+-----------------------------+
| log_bin                         | ON                          |
| log_bin_basename                | /var/lib/mysql/binlog       |
| log_bin_index                   | /var/lib/mysql/binlog.index |
| log_bin_trust_function_creators | OFF                         |
| log_bin_use_v1_row_events       | OFF                         |
| sql_log_bin                     | ON                          |
+---------------------------------+-----------------------------+

系统变量含义:

  • log_bin,是否开启二进制日志

  • log_bin_basename,二进制日志文件前缀,一个文件写满后会开启下一个,从 binlog.0000001 开始。

  • log_bin_index,二进制日志文件的索引

查看日志文件:

sudo ls -al /var/lib/mysql/ | grep binlog
-rw-r-----.  1 mysql mysql        831  7月 16 21:04 binlog.000001
-rw-r-----.  1 mysql mysql        180  7月 16 21:14 binlog.000002
-rw-r-----.  1 mysql mysql        180  7月 16 21:14 binlog.000003
-rw-r-----.  1 mysql mysql        180  7月 16 21:17 binlog.000004
-rw-r-----.  1 mysql mysql        180  7月 16 21:18 binlog.000005
-rw-r-----.  1 mysql mysql       2612  8月  4 09:37 binlog.000006
-rw-r-----.  1 mysql mysql        180  8月  4 09:42 binlog.000007
-rw-r-----.  1 mysql mysql       1486  8月  4 10:02 binlog.000008
-rw-r-----.  1 mysql mysql 1456538587  8月  4 10:49 binlog.000009
-rw-r-----.  1 mysql mysql 1459956598  8月  4 10:59 binlog.000010
-rw-r-----.  1 mysql mysql  779192108  8月  7 16:26 binlog.000011
-rw-r-----.  1 mysql mysql        176  8月  4 10:59 binlog.index

查看日志索引:

sudo cat /var/lib/mysql/binlog.index
./binlog.000001
./binlog.000002
./binlog.000003
./binlog.000004
./binlog.000005
./binlog.000006
./binlog.000007
./binlog.000008
./binlog.000009
./binlog.000010
./binlog.000011

日志格式

日志格式 含义
STATEMENT 基于SQL语句的日志记录,记录的是SQL语句,对数据进行修改的SQL都会记录
ROW 基于行的日志记录,记录的是每一行的数据变更(默认)
MIXED 混合了STATEMENT和ROW两种格式,默认采用STATEMENT,在某些特殊情况下会自动切换为ROW进行记录

查看当前二进制日志的格式:

mysql> show variables like '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+

使用 mysqlbinlog 工具可以查看二进制日志:

mysqlbinlog [参数选项]logfilename
参数
-d      指定数据库名称,只列出指定的数据库相关操作。
-o      忽略掉日志中的前n行命令。
-v      将行事件(数据变更)重构为SQL语句
-vv     将行事件(数据变更)重构为SQL语句,并输出注释信息

示例,修改表数据:

mysql> select * from score;
+----+-------+------+---------+------+
| id | name  | math | english | java |
+----+-------+------+---------+------+
|  1 | LiLei |   77 |      88 | NULL |
|  2 | Jack  |   87 |      66 | NULL |
+----+-------+------+---------+------+
2 rows in set (0.00 sec)
​
mysql> update score set math=math+1;
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2  Changed: 2  Warnings: 0
​
mysql> select * from score;
+----+-------+------+---------+------+
| id | name  | math | english | java |
+----+-------+------+---------+------+
|  1 | LiLei |   78 |      88 | NULL |
|  2 | Jack  |   88 |      66 | NULL |
+----+-------+------+---------+------+

查看二进制日志:

mysqlbinlog -d itcast binlog.000011

ROW 格式的二进制日志必须转换为 SQL 才能查看到数据变更,所以要使用-v参数:

mysqlbinlog -d itcast -v binlog.000011
### UPDATE `itcast`.`score`
### WHERE
###   @1=1
###   @2='LiLei'
###   @3=77
###   @4=88
###   @5=NULL
### SET
###   @1=1
###   @2='LiLei'
###   @3=78
###   @4=88
###   @5=NULL
### UPDATE `itcast`.`score`
### WHERE
###   @1=2
###   @2='Jack'
###   @3=87
###   @4=66
###   @5=NULL
### SET
###   @1=2
###   @2='Jack'
###   @3=88
###   @4=66
###   @5=NULL

输出中的 WHERE @1=1 @2='LiLei' ... 表示的是更新前的第一列值是1,第二列值是 LiLei 等。相对应的 SET 记录的是更新后的每一列的值。

修改二进制日志的格式:

cd /etc/my.cnf.d/
sudo vim mysql-server.cnf

在配置文件中添加:

binlog_format=STATEMENT

重启服务:

systemctl restart mysqld

再次修改表数据:

mysql> update score set math=math+1;

此时因为日志格式发生改变,会产生一个新的二进制日志,查看该日志:

mysqlbinlog -d itcast binlog.000012
# at 331
#250807 17:20:20 server id 1  end_log_pos 449 CRC32 0xd2ec43b5  Query   thread_id=8     exec_time=0     error_code=0
use `itcast`/*!*/;
SET TIMESTAMP=1754558420/*!*/;
update score set math=math+1
/*!*/;

可以看到日志中直接记录的是 SQL 而不是表数据。此外表结构发生变化时二进制日志中也会记录,但 SELECT 等查询语句不会被记录。

日志删除

对于比较繁忙的日志系统,每天生成的 binlog 数据巨大,如果长时间不清理,会占用大量磁盘空间。

可以通过以下几种方式清理日志:

指令 含义
reset master 删除全部 binlog 日志,日志编号从 binlog.000001 重新开始
purge master logs to 'binlog.xxxxxx' 删除 xxxxxx 编号之前的日志
purge master logs before 'yyyy-mm-dd hh24:mi:ss' 删除指定时间之前的日志

示例,当前的日志文件:

[root@192 mysql]# ls -al | grep binlog
-rw-r-----.  1 mysql mysql        831  7月 16 21:04 binlog.000001
-rw-r-----.  1 mysql mysql        180  7月 16 21:14 binlog.000002
-rw-r-----.  1 mysql mysql        180  7月 16 21:14 binlog.000003
-rw-r-----.  1 mysql mysql        180  7月 16 21:17 binlog.000004
-rw-r-----.  1 mysql mysql        180  7月 16 21:18 binlog.000005
-rw-r-----.  1 mysql mysql       2612  8月  4 09:37 binlog.000006
-rw-r-----.  1 mysql mysql        180  8月  4 09:42 binlog.000007
-rw-r-----.  1 mysql mysql       1486  8月  4 10:02 binlog.000008
-rw-r-----.  1 mysql mysql 1456538587  8月  4 10:49 binlog.000009
-rw-r-----.  1 mysql mysql 1459956598  8月  4 10:59 binlog.000010
-rw-r-----.  1 mysql mysql  779192501  8月  7 17:18 binlog.000011
-rw-r-----.  1 mysql mysql        480  8月  7 17:20 binlog.000012
-rw-r-----.  1 mysql mysql        192  8月  7 17:18 binlog.index

执行 SQL:

mysql> purge master logs to 'binlog.000003';
Query OK, 0 rows affected (0.01 sec)

现在的日志文件:

[root@192 mysql]# ls -al | grep binlog
-rw-r-----.  1 mysql mysql        180  7月 16 21:14 binlog.000003
-rw-r-----.  1 mysql mysql        180  7月 16 21:17 binlog.000004
-rw-r-----.  1 mysql mysql        180  7月 16 21:18 binlog.000005
-rw-r-----.  1 mysql mysql       2612  8月  4 09:37 binlog.000006
-rw-r-----.  1 mysql mysql        180  8月  4 09:42 binlog.000007
-rw-r-----.  1 mysql mysql       1486  8月  4 10:02 binlog.000008
-rw-r-----.  1 mysql mysql 1456538587  8月  4 10:49 binlog.000009
-rw-r-----.  1 mysql mysql 1459956598  8月  4 10:59 binlog.000010
-rw-r-----.  1 mysql mysql  779192501  8月  7 17:18 binlog.000011
-rw-r-----.  1 mysql mysql        480  8月  7 17:20 binlog.000012
-rw-r-----.  1 mysql mysql        160  8月  7 17:31 binlog.index

binlog.000003(不包含)之前的日志文件被删除了。

删除全部日志文件:

mysql> reset master;
Query OK, 0 rows affected (1.07 sec)

现在的日志文件:

[root@192 mysql]# ls -al | grep binlog
-rw-r-----.  1 mysql mysql      157  8月  7 17:34 binlog.000001
-rw-r-----.  1 mysql mysql       16  8月  7 17:34 binlog.index

MySQL 有一个变量表示二进制日志的过期时长,超过该时长的日志会被自动删除:

mysql> show variables like '%binlog_expire%';
+-------------------------------+---------+
| Variable_name                 | Value   |
+-------------------------------+---------+
| binlog_expire_logs_auto_purge | ON      |
| binlog_expire_logs_seconds    | 2592000 |
+-------------------------------+---------+

默认是 2592000 秒,即 30 天。

查询日志

查询日志中记录了客户端的所有操作语句。

默认情况下查询日志是未开启的。

查询日志相关的系统变量:

mysql> show variables like '%general%';
+------------------+------------------------+
| Variable_name    | Value                  |
+------------------+------------------------+
| general_log      | OFF                    |
| general_log_file | /var/lib/mysql/192.log |
+------------------+------------------------+

在 MySQL 配置文件中添加下面内容以开启查询日志:

# 开启查询日志
general_log=1
general_log_file=/var/lib/mysql/mysql_query.log

重启服务:

sudo systemctl restart mysqld

通过客户端执行以下 SQL:

mysql> show databases;
mysql> use itcast;
mysql> select * from student;

查看查询日志:

[root@192 mysql]# tail -n 10 mysql_query.log
2025-08-07T11:26:42.304730Z         8 Field List        student_v_3
2025-08-07T11:26:42.307498Z         8 Field List        tb_user
2025-08-07T11:26:42.320069Z         8 Field List        tb_user_ext
2025-08-07T11:26:42.324473Z         8 Field List        user_logs
2025-08-07T11:26:42.329862Z         8 Field List        user_v_pro_count
2025-08-07T11:26:42.332127Z         8 Query     show databases
2025-08-07T11:26:47.849681Z         8 Query     SELECT DATABASE()
2025-08-07T11:26:47.850623Z         8 Init DB   itcast
2025-08-07T11:26:50.798361Z         8 Query     show tables
2025-08-07T11:26:58.144991Z         8 Query     select * from student

慢查询日志

慢查询日志记录了所有执行时间超过系统变量 long_query_time 设置值并且扫描记录数不小于 min_examined_row_limit 的所有的 SQL 语句的日志,默认未开启。

long_query_time 默认为 10 秒,最小为0,精度可以到微妙。

慢查询相关的系统变量:

mysql> show variables like '%slow_query%';
+---------------------+-----------------------------+
| Variable_name       | Value                       |
+---------------------+-----------------------------+
| slow_query_log      | ON                          |
| slow_query_log_file | /var/lib/mysql/192-slow.log |
+---------------------+-----------------------------+

这里慢查询日志文件是/var/lib/mysql/192-slow.log。

修改配置文件开启慢查询日志:

# 开启慢查询日志
slow_query_log=1
# 超过2秒的SQL作为慢查询进行记录
long_query_time=2

执行一个慢查询:

mysql> select count(*) from tb_sku;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+

查看慢查询日志:

[root@192 mysql]# tail -n 10 192-slow.log
Time                 Id Command    Argument
/usr/libexec/mysqld, Version: 8.0.41 (Source distribution). started with:
Tcp port: 3306  Unix socket: /var/lib/mysql/mysql.sock
Time                 Id Command    Argument
# Time: 2025-08-07T11:34:18.535796Z
# User@Host: root[root] @ localhost []  Id:     8
# Query_time: 22.965399  Lock_time: 0.000037 Rows_sent: 1  Rows_examined: 0
use test;
SET timestamp=1754566435;
select count(*) from tb_sku;

默认情况下,慢查询日志不会记录管理语句,也不会记录不使用索引进行查找的查询。如果要改变这一行为,可以修改配置文件:

#记录执行较慢的管理语句
log_slow_admin_statements=1
#记录执行较慢的未使用索引的语句
log_queries_not_using_indexes = 1

参考资料

  • 黑马程序员 MySQL数据库入门到精通

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: MySQL 日志
最后更新:2025年8月7日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号