Mysql日志管理

日志简介

错误日志

sql 复制代码
作用: 记录mysql数据库的一般状态信息及报错信息,是我们对于数据库常规报错处理的常用日志。
默认位置: DATA_DIR/hostname.err
开启方式:(MySQL安装完后默认开启)

#查询
mysql> select @@log_error;
+-------------+
| @@log_error |
+-------------+
| ./mysql.log |
+-------------+
mysql> show variables like 'log_error';
+---------------+-------------+
| Variable_name | Value |
+---------------+-------------+
| log_error | ./mysql.log |
+---------------+-------------+
#修改
vim /etc/my.cnf
[mysqld]
log_error=/data/mysql/data/mysql.log

一般查询日志

sql 复制代码
作用: 记录mysql所有执行成功的SQL语句信息,可以做审计用,但是我们很少开启。
默认位置: DATA_DIR/hostname.log
开启方式:(MySQL安装完之后默认不开启)

#查看
mysql> show variables like '%general%';
+------------------+---------------------------+
| Variable_name | Value |
+------------------+---------------------------+
| general_log | OFF |
| general_log_file | /data/mysql/data/db02.log |
+------------------+---------------------------+
#修改
vim /etc/my.cnf
[mysqld]
general_log=1
general_log_file=/data/mysql/data/db02.log

二进制日志(binlog)

binlog概述

sql 复制代码
作用:
记录已提交的DML事务语句,并拆分为多个事件(event)来进行记录
记录所有DDL、DCL等语句 ,实现数据恢复、主从复制
总之,二进制日志会记录所有对数据库发生修改的操作
二进制日志模式: 
STATEMENT:SBR,语句模式,记录操作语句本身,MySQL5.6的默认模式
优点:简单明了,容易被看懂,就是sql语句,记录时不需要太多的磁盘空间。
缺点:记录不够严谨。
ROW:RBR,行模式,即数据行的变化过程,MySQL5.7的默认模式
优点:记录更加严谨。
缺点:有可能会需要更多的磁盘空间,不太容易被读懂。
MIXED:MBR,以上两者的混合模式
企业推荐使用row模式

binlog配置

sql 复制代码
log_bin:binlog开关、设定存放位置文件的路径及文件名前缀
server_id(5.6不需要添加此参数,5.7以上必须加)
生产要求:日志和数据分开存放
sql 复制代码
# 创建binlog目录,并修改归属
# mkdir -p /data/mysql/binlog
# chown -R mysql.mysql /data/mysql/binlog

# 修改MySQL配置文件
# vim /etc/my.cnf
[mysqld]
server_id=6
log_bin=/data/mysql/binlog/mysql-bin

# 重启mysqld
# systemctl restart mysqld

# 系统下查看binlog
# ls /data/mysql/binlog/mysql-bin.*
total 8
-rw-r----- 1 mysql mysql 154 Apr 7 22:52 mysql-bin.000001
-rw-r----- 1 mysql mysql 36 Apr 7 22:52 mysql-bin.index

# MySQL中查看
# 查看binlog的参数
mysql> show variables like '%log_bin%';
+---------------------------------+------------------------------------+
| Variable_name | Value |
+---------------------------------+------------------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql/binlog/mysql-bin |
| log_bin_index | /data/mysql/binlog/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+------------------------------------+

# 查看binlog模式
mysql> show variables like 'binlog_format';

# 查看所有的binlog文件
mysql> show binary logs;

# 查看查看当前日志工作
mysql> show master logs;

# 查看正在工作的binlog
mysql> show master status;

# 查看指定binlog文件的事件
mysql> show binlog events in 'mysql-bin.000001';
+------------------+-----+----------------+-----------+-------------+------------
---------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info 
|
+------------------+-----+----------------+-----------+-------------+------------
---------------------------+
| mysql-bin.000001 | 4 | Format_desc | 6 | 123 | Server
ver: 5.7.32-log, Binlog ver: 4
| mysql-bin.000001 | 123 | Previous_gtids | 6 | 154 |
| mysql-bin.000001 | 154 | Anonymous_Gtid | 6 | 219 | SET
@@SESSION.GTID_NEXT= 'ANONYMOUS'
| mysql-bin.000001 | 219 | Query | 6 | 322 | create
database binlong 
| mysql-bin.000001 | 322 | Anonymous_Gtid | 6 | 387 | SET
@@SESSION.GTID_NEXT= 'ANONYMOUS'
| mysql-bin.000001 | 387 | Query | 6 | 478 | drop
database binlong 
| mysql-bin.000001 | 478 | Anonymous_Gtid | 6 | 543 | SET
@@SESSION.GTID_NEXT= 'ANONYMOUS'
| mysql-bin.000001 | 543 | Query | 6 | 643 | create
database binlog

bin_log头部标记:
5.6 前120个Position号
5.7 前123个Position号
注释:以上输出中每一行为一个事件
Log_name:日志名
Pos:事件开始的Position *****
Event_type:事件类型
Server_id:发生在哪台机器的事件 //主从时区分机器
End_log_pos:事件结束的位置号 *****
Info:事件内容

binlog事件

sql 复制代码
二进制日志的最小记录单元
对于DDL,DCL,一个语句就是一个event
对于DML语句来讲:只记录已提交的事务。
event的组成
事件的开始标识(start position)
at
事件内容
事件的结束标识(stop position)
end_log_pos

例如以下例子,就被分为了4个event
position号码(字节偏移量)
begin; 120 - 340
DML1 340 - 460
DML2 460 - 550
commit; 550 - 760
作用:方便对日志进行截取,指定部分日志进行数据恢复

binlog内容分析及数据恢复

sql 复制代码
案例练习1:
环境
create database test;
use test
create table t1(id int);
insert into t1 values(1);
insert into t1 values(2),(3),(4);
模拟误操作,删除2
delete from t1 where id=2;
要求:将上述误操作恢复
1.观察事务日志,找到误操作之前的节点
需要解码,通过误操作前的commit来寻找end_log_position
mysqlbinlog --base64-output=decode-rows -v /data/mysql/binlog/mysql-bin.000001
# at 1220
#240228 14:49:02 server id 6  end_log_pos 1251 CRC32 0xa44eb22a 	Xid = 32
COMMIT/*!*/;
# at 1251
#240228 14:50:01 server id 6  end_log_pos 1316 CRC32 0x7bc48a6e 	Anonymous_GTID	last_committed=4	sequence_number=5	rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1316
#240228 14:49:44 server id 6  end_log_pos 1388 CRC32 0x71c50f4b 	Query	thread_id=2	exec_time=0	error_code=0
SET TIMESTAMP=1709102984/*!*/;
BEGIN
/*!*/;
# at 1388
#240228 14:49:44 server id 6  end_log_pos 1433 CRC32 0x2b1a91b1 	Table_map: `test`.`t1` mapped to number 108
# at 1433
#240228 14:49:44 server id 6  end_log_pos 1473 CRC32 0x587544fc 	Delete_rows: table id 108 flags: STMT_END_F
### DELETE FROM `test`.`t1`
...

2.导出该节点之前binlog信息
mysqlbinlog --start-position=219 --stop-position=1251 /data/mysql/binlog/mysql-bin.000003 > /tmp/binlog.sql

3.导入到数据库中
在mysql的交互环境中导入上述步骤的sql文件的内容
#1.临时关闭binlog
set sql_log_bin=0;

#2.source导入
drop table test.t1;
source /tmp/binlog.sql

#3.查询数据是否恢复
select * from test.t1;

#4.开启binlog
set sql_log_bin=1;
也可以关闭会话,重新登录

案例练习2
环境
create table t2(id int);
insert into t2 values(5),(6),(7);
# 误操作1
update t1 set id=33 where id=3;
insert into t2 values(8),(9);
# 误操作2
delete from t1 where id=1;
create table t3(id int);
insert into t3 values(111),(222);

1.观察事务日志,找到误操作之前的节点
需要解码,通过误操作前的commit来寻找end_log_position
mysqlbinlog --base64-output=decode-rows -v /data/mysql/binlog/mysql-bin.000001
# at 1220
#240228 14:49:02 server id 6  end_log_pos 1251 CRC32 0xa44eb22a 	Xid = 32
COMMIT/*!*/;
# at 1251
#240228 14:50:01 server id 6  end_log_pos 1316 CRC32 0x7bc48a6e 	Anonymous_GTID	last_committed=4	sequence_number=5	rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1316
#240228 14:49:44 server id 6  end_log_pos 1388 CRC32 0x71c50f4b 	Query	thread_id=2	exec_time=0	error_code=0
SET TIMESTAMP=1709102984/*!*/;
BEGIN
/*!*/;
# at 1388
#240228 14:49:44 server id 6  end_log_pos 1433 CRC32 0x2b1a91b1 	Table_map: `test`.`t1` mapped to number 108
# at 1433
#240228 14:49:44 server id 6  end_log_pos 1473 CRC32 0x587544fc 	Delete_rows: table id 108 flags: STMT_END_F
### DELETE FROM `test`.`t1`
...

根据上述细节分析,我们的有效数据有三段
test库,t1表起始:672
test库,t1表结束:1509

t2表起始:1762
t2表结束:2187

t3表起始:2957
t3表结束:3312

2.导出该节点之前binlog信息
在shell中使用mysqlbinlog工具导出上述结果
mysqlbinlog --start-position=672 --stop-position=1509 /data/mysql/binlog/mysql-bin.000001 > /tmp/binlog1.sql
mysqlbinlog --start-position=1762 --stop-position=2187 /data/mysql/binlog/mysql-bin.000001 > /tmp/binlog2.sql
mysqlbinlog --start-position=2957 --stop-position=3312 /data/mysql/binlog/mysql-bin.000001 > /tmp/binlog3.sql

3.导入到数据库中
在mysql的交互环境中导入上述步骤的sql文件的内容
#1.临时关闭binlog
set sql_log_bin=0;

#2.source导入
drop database test;
source /tmp/binlog1.sql
source /tmp/binlog2.sql
source /tmp/binlog3.sql

#3.查询数据是否恢复
select * from test.t1;
select * from test.t2;
select * from test.t3;

#4.开启binlog
set sql_log_bin=1;

也可以关闭会话,重新登录

binlog日志阈值管理

sql 复制代码
1.刷新binlog

mysql> flush logs; 

mysqladmin -uroot -p flush-logs; 

重启数据库时 
设置binlog上限(max_binlog_size 默认是1G大小)。 

2.删除binlog
1.手动删除
1)使用PURGE手动删除,不会重置binlog编号
mysql> PURGE BINARY LOGS BEFORE now() - INTERVAL 3 day; //删除从现在开始三天之前的二
进制日志
mysql> PURGE BINARY LOGS TO 'mysql-bin.000003'; //删除到哪里为止
2)使用reset master;删除所有binlog,并重新计数(从000001开始)
mysql> reset master;
2.自动删除
设置超时时间
临时生效的
SET GLOBAL expire_logs_days= 7;
永久生效:
vim /etc/my.cnf
expire_logs_days=7
自动删除设置依据:至少是一个全备周期+1,企业建议至少2个全备周期+1

慢查询日志

慢日志作用

记录慢SQL语句的日志,定位低效SQL语句的工具日志默认没开启

慢日志配置

sql 复制代码
vim /data/3307/my.cnf
slow_query_log=1 #指定是否开启慢查询日志
slow_query_log_file=/data/mysql/slow.log #指定慢日志文件存放位置,可以为空,系统会给一个
缺省的文件host_name-slow.log
long_query_time=0.05 #设定慢查询的阀值,超出次设定值的SQL即被记录到慢查询日志,缺省值为10s
log_queries_not_using_indexes=1 #不使用索引的慢查询日志是否记录到日志中
min_examined_row_limit=100 #查询检查返回少于该参数指定行的SQL不被记录到慢查询日志,鸡肋
进入数据库:查看参数是否生效
mysql> show variables like 'long_query_time';

模拟慢日志环境

sql 复制代码
use world
create table t1 select * from city;
insert into t1 select * from t1;
insert into t1 select * from t1;
commit;
insert into t1 select * from t1;
insert into t1 select * from t1;
commit;
insert into t1 select * from t1;
insert into t1 select * from t1;
commit;
select count(*) from t1;
select * from t1 group by id;

分析慢日志

sql 复制代码
1.mysqldumpslow命令
mysqldumpslow -s c -t 10 /data/mysql/slow.log
这会输出记录次数最多的10条SQL语句,其中:
-s
是表示按照何种方式排序,c、t、l、r
分别是按照记录次数、时间、查询时间、返回的记录数来排序
ac、at、al、ar,表示相应的倒叙
-t
是top n的意思,即为返回前面多少条的数据;
-g,
后边可以写一个正则匹配模式,大小写不敏感的;
例子:
/path/mysqldumpslow-s r -t 10 /database/mysql/slow-log
得到返回记录集最多的10个查询。
/path/mysqldumpslow-s t -t 10 -g "left join"/database/mysql/slow-log
得到按照时间排序的前10条里面含有左连接的查询语句。

2.pt-query-digest
pt-query-digest基本使用:
下载二进制包地址
https://www.percona.com/downloads/percona-toolkit/LATEST/
安装软件包支持:(不同的版,依赖包不一样)
yum install -y *Dumper* *MD5*
/xxx/bin/pt-query-digest /data/mysql/slow.log
扩展:Anemometer基于pt-query-digest将MySQL慢查询可视化
httpss://github.com/box/Anemometer 可视化代码下载
相关推荐
清水白石00844 分钟前
从一个“支付状态不一致“的bug,看大型分布式系统的“隐藏杀机“
java·数据库·bug
Python私教5 小时前
model中能定义字段声明不存储到数据库吗
数据库·oracle
mqiqe8 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
工业甲酰苯胺8 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
BestandW1shEs8 小时前
谈谈Mysql的常见基础问题
数据库·mysql
重生之Java开发工程师8 小时前
MySQL中的CAST类型转换函数
数据库·sql·mysql
教练、我想打篮球8 小时前
66 mysql 的 表自增长锁
数据库·mysql
Ljw...8 小时前
表的操作(MySQL)
数据库·mysql·表的操作
哥谭居民00018 小时前
MySQL的权限管理机制--授权表
数据库