日志简介
错误日志
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 可视化代码下载