默认开启,默认存放目录 /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
文章评论