1 MySQL日志介绍
可以简单分为:
- 数据库服务通用日志:记录数据操作的管理命令,记录连接数据库的用户信息
- 数据库服务错误日志:记录数据库服务运行情况、异常宕机、无法启动、无法建立主从
- 数据库服务二进制日志:记录数据库写入/更新语句信息,可以用于恢复数据/实现主从同步
- 数据库服务慢查询日志:记录数据库查询语句信息 可以用于分析处理慢查询语句
1.1 通用日志
1.查看当前的通用日志开启状态,可以发现没有开启
mysql> show variables like '%general_log%';
+------------------+--------------------------+
| Variable_name | Value |
+------------------+--------------------------+
| general_log | OFF |
| general_log_file | /data/3306/data/db51.log |
+------------------+--------------------------+
2.创建日志存放目录并修改目录权限
mkdir -p /data/3306/log
chown -R mysql.mysql /data/3306/log
3.修改数据库配置文件 my.cnf 后,重新启动数据库
[mysqld]
...
general_log=ON
general_log_file=/data/3306/log/general.log
4.确认开启成功:可以看到相关日志
[root@db51~]# cat /data/3306/log/general.log
/usr/local/mysql/bin/mysqld, Version: 8.0.26 (MySQL Community Server - GPL). started with:
Tcp port: 3306 Unix socket: /tmp/mysql.sock
Time Id Command Argument
2024-12-04T13:38:50.914070Z 7 Query set global sql_safe_updates=1;
2024-12-04T13:38:56.421739Z 9 Connect root@localhost on using Socket
2024-12-04T13:38:56.422138Z 9 Query select @@version_comment limit 1
1.2 错误日志
- 最好先创建这个错误日志文件,有可能MySQL不会自己创建日志文件
1.查看错误日志开启情况,发现默认输出到了终端,而且不会保存下来
mysql> show variables like '%log_error%';
+----------------------------+----------------------------------------+
| Variable_name | Value |
+----------------------------+----------------------------------------+
| binlog_error_action | ABORT_SERVER |
| log_error | stderr |
| log_error_services | log_filter_internal; log_sink_internal |
| log_error_suppression_list | |
| log_error_verbosity | 2 |
+----------------------------+----------------------------------------+
2.修改 my.cnf 后重启数据库
touch /data/3306/log/error.err && chown mysql.mysql /data/3306/log/error.log
[mysqld]
...
log_error=/data/3306/log/error.log
3.查看错误日志内容:
2 二进制日志binlog
- 开启事务后,不提交是看不到操作记录的
- 每次重启数据库后,二进制日志会切割,产生新的文件
2.1 binlog相关配置
1.查看开启状态;8.0版本默认开启了,其他的低版本数据库需要手动开启
mysql> show variables like '%log_bin%';
+---------------------------------+------------------------------+
| Variable_name | Value |
+---------------------------------+------------------------------+
| log_bin | ON |
| log_bin_basename | /data/3306/data/binlog |
| log_bin_index | /data/3306/data/binlog.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+------------------------------+
og_bin=ON
:是否关闭或开启二进制日志log_bin_basename
:设置二进制日志保存路径,以及名称信息log_bin_index
:识别所有二进制日志,以及最新的二进制日志sql_log_bin
:是否将写入的语句信息记录到binlog
2.1 设置binlog保存路径
2.手动设置二进制日志保存路径(可选),修改 My.cnf
[mysqld]
...
log_bin=/data/3306/log/wzy_binlog
3.多次启动数据库后查看相关日志
[root@db51~]# ll /data/3306/log/wzy_binlog.*
-rw-r----- 1 mysql mysql 179 Dec 4 22:01 /data/3306/log/wzy_binlog.000001
-rw-r----- 1 mysql mysql 179 Dec 4 22:02 /data/3306/log/wzy_binlog.000002
-rw-r----- 1 mysql mysql 156 Dec 4 22:02 /data/3306/log/wzy_binlog.000003
-rw-r----- 1 mysql mysql 99 Dec 4 22:02 /data/3306/log/wzy_binlog.index
可以看到 wzy_binlog.index 被MySQL进程打开了
[root@db51log]# lsof wzy_binlog.index
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 17015 mysql 3u REG 8,2 99 6161138 wzy_binlog.index
4.使用 mysqlbinlog
命令查看二进制日志,⚠️注意使用同版本的命令查看
server ID 的设置
作用影响binlog中 sever id的显示
1.修改my.cnf后重启
[mysqld]
...
server_id=3306
2.查看当前binlog中的 **Server_id ** 已经显示为3306了
mysql> show binlog events in 'wzy_binlog.000008';
+-------------------+-----+----------------+-----------+-------------+-----------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+----------------+-----------+-------------+-----------------------------------+
| wzy_binlog.000008 | 4 | Format_desc | 3306 | 125 | Server ver: 8.0.26, Binlog ver: 4 |
| wzy_binlog.000008 | 125 | Previous_gtids | 3306 | 156 | |
+-------------------+-----+----------------+-----------+-------------+-----------------------------------+
binlog_rsync刷盘(第1个双一配置)
参考链接:https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html
sync_binlog
是 MySQL 中的一个配置选项,用于控制二进制日志(binary log)的同步频率。会影响主从的同步频率
-
0:禁用二进制日志的自动同步。MySQL 会在每个事务提交时将二进制日志写入操作系统缓存,但不会主动将缓存中的数据刷新到磁盘。这种配置可以提高性能,但在发生故障时可能会丢失一些数据
-
1(默认):每次事务提交时都将二进制日志同步到磁盘。这是最安全的设置,可以确保在发生故障时不会丢失任何数据,但可能会影响性能
-
XX:(大于1的整数):每写入 N 个事务后,将二进制日志同步到磁盘。这种设置在性能和数据安全性之间取得了平衡。例如,设置
sync_binlog = 1000
表示每提交 1000 个事务后,MySQL 会将二进制日志同步到磁盘
1.全局配置示例,my.cnf
[mysqld]
...
sync_binlog=1000
2.查看到已生效
mysql> select @@sync_binlog;
+---------------+
| @@sync_binlog |
+---------------+
| 1000 |
+---------------+
binlog的记录格式
一、SBR(语句格式记录)
记录的是执行的 SQL 语句本身。这意味着每个执行的修改数据库状态的 SQL 语句都会被记录到 Binlog 中,无论这些语句是如何影响数据的。
设置方式:
[mysqld]
binlog_format=statement
二、RBR(行格式记录)
记录的是数据行的变化,而不是 SQL 语句本身。每次对数据表的操作都会记录每一行的具体修改内容。无论 SQL 语句如何执行,只要影响了数据表中的行,都会在 Binlog 中记录每一行的实际变更
设置方式:
在mysql8.0中默认的方式
[mysqld]
binlog_format=row
查看binlog中的sql语句可以这样:mysqlbinlog --base64-output=decode-rows -vvv
[root@db51log]# mysqlbinlog --base64-output=decode-rows -vvv wzy_binlog.000008 | grep -iA 3 insert
### INSERT INTO `wzy_white`.`wzy_white_table`
### SET
### @1=1 /* INT meta=0 nullable=1 is_null=0 */
### @2='wzy01' /* VARSTRING(1020) meta=1020 nullable=1 is_null=0 */
如果直接查看,看到的就是编码后的密文
[root@db51log]# mysqlbinlog wzy_binlog.000008 | egrep -v '^/|^#'
DELIMITER /*!*/;
ROLLBACK/*!*/;
BINLOG '
KmxQZw/qDAAAeQAAAH0AAAAAAAQAOC4wLjI2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAqbFBnEwANAAgAAAAABAAEAAAAYQAEGggAAAAICAgCAAAACgoKKioAEjQA
CigBlovdRg==
'/*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
三、mixed (混合记录方式)
混合模式是 STATEMENT 模式和 ROW 模式的结合。在这种模式下,MySQL 会根据实际情况选择是记录 SQL 语句还是行数据。对于某些语句(例如不确定性语句),MySQL 会选择 ROW 模式;而对于其他确定性的语句,则使用 STATEMENT 模式
配置方式:
[mysqld]
binlog_format=mixed
binlog切割
方式1:flush手动切割
flush手动日志切割
flush logs;
切割日志之后新增了日志文件
mysql> flush logs;
mysql> show binary logs;
+--------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+--------------------+-----------+-----------+
| 3306-binlog.000001 | 179 | No |
| 3306-binlog.000002 | 205 | No |
| 3306-binlog.000003 | 156 | No |
+--------------------+-----------+-----------+
方式2:重启数据库实现切割
systemctl restart mysqld
方式3:自动切割
1.查看到:默认为binlog文件体积达到1个G开始切割
mysql> select @@max_binlog_size;
+-------------------+
| @@max_binlog_size |
+-------------------+
| 1073741824 |
+-------------------+
# 也可以自定义切割大小:例如改为1MB切割
mysql> set global max_binlog_size=1048576;
2.基于时间的日志切割
# 查看binlog过期时间,默认是按照秒的方式计时
mysql> show variables like '%expire_logs%';
+----------------------------+---------+
| Variable_name | Value |
+----------------------------+---------+
| binlog_expire_logs_seconds | 2592000 |
| expire_logs_days | 0 |
+----------------------------+---------+
# 更改过期时间 (按照秒的方式计时)
mysql> set global binlog_expire_logs_seconds=9999999;
# 也可以修改为按照天的方式计时
mysql> SET GLOBAL expire_logs_days = 7;
mysql> show variables like '%expire_logs%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| binlog_expire_logs_seconds | 0 |
| expire_logs_days | 7 |
+----------------------------+-------+
binlog删除
如果binlog数据量比较多,需要清理。可以使用rm命令删除binlog,或者在mysql中执行命令删除指定的binlog
方式1:删除指定binlog以前的日志。例如把 binlog.000002以前的都删除掉
mysql> show binary logs;
+-------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+-------------------+-----------+-----------+
| wzy_binlog.000001 | 1241 | No |
| wzy_binlog.000002 | 156 | No |
+-------------------+-----------+-----------+
mysql> purge binary logs to 'wzy_binlog.000002';
mysql> show binary logs;
+-------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+-------------------+-----------+-----------+
| wzy_binlog.000002 | 156 | No |
+-------------------+-----------+-----------+
方式2:基于时间的binlog删除,例如删除指定日期以前的binlog
mysql> PURGE BINARY LOGS BEFORE '2023-04-02 22:46:26';
binlog日志清理原则:1-2两个全备周期前的binlog日志做清理
周一 周二 周日
数据信息 数据信息 .... 数据信息 全备
binlog001 binlog002 binlog07 backup.sql 1个备份周期
周一 周二 周日
数据信息 数据信息 .... 数据信息 全备
binlog008 binlog009 binlog14 backup.sql 2个备份周期
2.2 binlog相关信息的查看
binlog状态查看
1.获取数据库服务中所有的二进制日志信息
mysql> show binary logs;
+-------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+-------------------+-----------+-----------+
| wzy_binlog.000001 | 179 | No |
| wzy_binlog.000002 | 179 | No |
| wzy_binlog.000003 | 362 | No |
+-------------------+-----------+-----------+
2.获取正在使用的二进制日志信息,里面记录了 起始位置点,黑名单配置
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| wzy_binlog.000003 | 362 | | | |
+-------------------+----------+--------------+------------------+-------------------+
查看日志详情
show binlog events in '3306-binlog.000003';
binlog过滤
当使用 show binlog events XXX
查看的binlog输出的无用信息过多时,就可以使用过滤功能。查找想要的语句
1.开启该功能,回到原来的查看方式为:pager cat
mysql> pager less;
2.再次使用 show binlog events
查看时,就会进入类似vim的界面,输入 /drop database
可以过滤删库语句
另一种方式:在命令行进行过滤
mysql -e "show binlog events in 'binlog.000002'"|grep "drop database"
2.3 binlog的黑白名单功能
Binlog 的黑白名单功能用于控制哪些数据库或表的变更事件会被记录到 Binlog 中,或者哪些数据库和表的变更事件不会被记录。
白名单:
- 白名单功能允许指定哪些数据库或表的变更会被记录到 Binlog 中。通过设置白名单,可以确保只有特定的数据库或表的操作被日志化,其他不相关的数据库或表的操作将不会出现在 Binlog 中
黑名单:
-
概念:配置指定哪些数据库或表的变更将不会被记录到 Binlog 中。通过黑名单,可以避免不希望同步或记录的数据库或表的操作出现在 Binlog 中
-
作用
-
避免记录敏感数据泄露
-
节省存储空间
-
1.设置白名单库 wzy_white ,黑名单库 wzy_bkack 。如果要设置多个,则写多行即可。然后重启数据库
vim my.cnf
...
[mysqld]
binlog_ignore_db=wzy_black
binlog_do_db=wzy_white
重启后查看当前状态
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| wzy_binlog.000007 | 156 | wzy_white | wzy_black | |
+-------------------+----------+--------------+------------------+-------------------+
2.创建对应的库,创建表测试
mysql> create database wzy_white;
mysql> use wzy_white;
mysql> create table wzy_white_table (id int, name varchar(255));
mysql> create database wzy_black;
mysql> use wzy_black;
mysql> create table wzy_black_table (id int, name varchar(255));
3.查看当前日志事件,发现库 wzy_black 没有被记录
mysql> show binlog events in 'wzy_binlog.000007';
+-------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| wzy_binlog.000007 | 4 | Format_desc | 1 | 125 | Server ver: 8.0.26, Binlog ver: 4 |
| wzy_binlog.000007 | 125 | Previous_gtids | 1 | 156 | |
| wzy_binlog.000007 | 156 | Anonymous_Gtid | 1 | 233 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| wzy_binlog.000007 | 233 | Query | 1 | 356 | create database wzy_white /* xid=5 */ |
| wzy_binlog.000007 | 356 | Anonymous_Gtid | 1 | 433 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| wzy_binlog.000007 | 433 | Query | 1 | 587 | use `wzy_white`; create table wzy_white_table (id int, name varchar(255)) /* xid=10 */ |
+-------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
2.3 binlog的事务记录功能
-
ddl语句 :创建库 创建表 … 单个语句就是一个事务/事件
-
dml语句 :begin 添加 修改 删除 commit。这些操作不会显式地直接记录到binlog中
-
mysql8默认开启了事务自动开启和提交
-
mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+
-
1.在 wzy_white 库中插入数据
mysql> use wzy_white;
mysql> insert into wzy_white_table values (1,'wzy01');
2.查看binlog事件,可以发现有对表的操作。但是没有记录明显的数据信息。
不过可以在在通用日志中看到具体的数据插入信息
[root@db51log]# grep -n 'insert into wzy_white_table' general.log
156:2024-12-04T15:00:56.846639Z 9 Query insert into wzy_white_table values (1,'wzy01')
参数信息配置0:表示由操作系统缓存自己决定,什么时候刷新日志到磁盘中;
2.4 binlog的备份
1.db02主机创建存放备份日志的目录
mkdir -pv /backup/binlog_3306
2.配置db02主机拉取db01主机的日志
[root@db52~]# cd /backup/binlog_3306/
[root@db52binlog_3306]# pwd
/backup/binlog_330
mysqlbinlog \
-R --host=10.0.0.51 --port=3306 \
--user=root --password=123456 \
--raw --stop-never wzy_binlog.000003 &
--rwa
表示将二进制日志文件中的内容以原始格式(不解码)输出
--stop-never
一直拉取
3.验证,在db52节点查看拉取过来的日志:
[root@db52binlog_3306]# ll
total 28
-rw-r-----. 1 root root 1247 Dec 5 00:35 wzy_binlog.000003
-rw-r-----. 1 root root 179 Dec 5 00:35 wzy_binlog.000004
-rw-r-----. 1 root root 571 Dec 5 00:35 wzy_binlog.000005
-rw-r-----. 1 root root 179 Dec 5 00:35 wzy_binlog.000006
-rw-r-----. 1 root root 610 Dec 5 00:35 wzy_binlog.000007
-rw-r-----. 1 root root 490 Dec 5 00:35 wzy_binlog.000008
-rw-r-----. 1 root root 156 Dec 5 00:35 wzy_binlog.000009
4.db01的binlog刷新,产生新的日志也会实时同步到db02上面
2.5 单个binlog实现数据找回
1.创建数据库 binwzy 和表 wzy ,插入一些数据,然后把表删除 drop table t1;
模拟数据损坏和误删除。
create database binwzy; use binwzy;
create table wzy (id int);
insert into wzy values (1),(2),(3);
drop table wzy;
查看binlog记录的操作。提示:如果设置了黑白名单,binlog是没有相关记录的,除非设置了白名单
2.使用mysqlbinlog命令截取操作记录,并写入sql文件。
截取创建表之后至删除表之前的起始位置ID
[root@db51~]# mysqlbinlog \
--start-position=347 \
--stop-position=829 \
/data/3306/log/wzy_binlog.000001 \
>/tmp/bindb.sql;
3.执行数据恢复
恢复前关闭日志记录,防止录入重复日志,数据恢复之后记得开启
set global sql_log_bin=0;
source /tmp/bindb.sql
4.可以看到数据恢复成功
mysql> select * from wzy;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 慢查询日志
慢查询日志介绍
慢日志主要是用于以文本形式记录数据库服务运行过程中,执行过程较慢的语句;利用慢日志信息生成的信息,可以在日常巡检过程中,通过日志定位SQL语句性能问题;
以下为慢查询的相关系统变量:
slow_query_log
:0关闭,1开启slow_query_log_file
:义慢查询日志存储路径以及名称信息long_query_time
:查询耗时超时设置log_queries_not_using_indexes
:没有走索引的语句会记录到慢查询日志中;0关闭,1开启
开启慢查询记录
1.相关配置,my.cnf配置内容示例,修改后重启数据库
[mysqld]
slow_query_log=1
slow_query_log_file=/data/3306/log/slow.log
long_query_time=0.01
log_queries_not_using_indexes=1
2.慢查询日志内容,cat slow.loq
,以其中一条查询为例:
SET timestamp=1733409313;
SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA;
# Time: 2024-12-05T14:36:46.428468Z
# User@Host: root[root] @ [10.0.0.253] Id: 10
# Query_time: 0.156476 Lock_time: 0.000164 Rows_sent: 0 Rows_examined: 1000001
SET timestamp=1733409406;
SELECT * FROM t100w WHERE k1 LIKE '%wzy6%';
lock_time锁机制
分析慢查询日志
查看时所用的参数
-s
:sort,指定排序方式-c
:按照sql出现次数排序-t
:出现的前多少次-s
: 限制输出的查询数量。例如:-s 10
只输出前 10 个慢查询-a
:显示所有列的信息
[root@db51log]# mysqldumpslow -s c -t 2 /data/3306/log/slow.log
Reading mysql slow query log from /data/3306/log/slow.log
Count: 1 Time=0.70s (0s) Lock=0.00s (0s) Rows=1000000.0 (1000000), root[root]@localhost
select * from t100w where num != 'S'
Count: 1 Time=0.24s (0s) Lock=0.00s (0s) Rows=49156.0 (49156), root[root]@localhost
select * from t100w where num like 'S'
Id: 10
# Query_time: 0.156476 Lock_time: 0.000164 Rows_sent: 0 Rows_examined: 1000001
SET timestamp=1733409406;
SELECT * FROM t100w WHERE k1 LIKE '%wzy6%';
lock_time锁机制
分析慢查询日志
查看时所用的参数
-s
:sort,指定排序方式-c
:按照sql出现次数排序-t
:出现的前多少次-s
: 限制输出的查询数量。例如:-s 10
只输出前 10 个慢查询-a
:显示所有列的信息
[root@db51log]# mysqldumpslow -s c -t 2 /data/3306/log/slow.log
Reading mysql slow query log from /data/3306/log/slow.log
Count: 1 Time=0.70s (0s) Lock=0.00s (0s) Rows=1000000.0 (1000000), root[root]@localhost
select * from t100w where num != 'S'
Count: 1 Time=0.24s (0s) Lock=0.00s (0s) Rows=49156.0 (49156), root[root]@localhost
select * from t100w where num like 'S'