113. MySQL 日志管理

1.错误日志

1.1 作用
排错.
MySQL 启动和工作过程状态,警告,错误. 

1.2 配置 
默认开启.存储位置, datadir/hostname.err
vim /etc/my.cnf 
...
log_error=/data/mysql/data_3306/mysql.log	#日志文件需提交创建及授权
...
/etc/init.d/mysqld restart	重启生效

1.3 在mysql.log日志文件中查看错误;找关键字“ERROR” 进行排错,一般错误提示的很人性化,通常可以排查90%以上的错误
[ERROR]

2.二进制日志(binlog)

2.1 作用
数据恢复;
主从复制.
记录的是所有变化类(语句)的操作(DDL,DML,DCL).

2.2 5.7版本配置 
vim /etc/my.cnf 
...
server_id=6 
log_bin=/data/mysql/binlog_3306/mysql-bin	#目录需提前创建及授权,mysql-bin为文件名的前缀
binlog_format=row
sync_binlog=1	#每次事务提交,立即刷写binlog日志,为了安全
...
/etc/init.d/mysqld restart	#重启生效

2.3 binlog 对于不同语句的记录格式 
(1)非事务型语句: DDL  DCL 
以statement语句模式记录

(2)事务型语句(insert ,update  ,delete )
begin;  A   ;  commit;
只记录提交的事务.
记录格式,三种模式:
		RBR  :  ROW模式(DML默认模式), 记录数据行的变化. 记录够准确.
mysql> select @@binlog_format;
+-----------------+
| @@binlog_format |
+-----------------+
| ROW             |
+-----------------+
1 row in set (0.00 sec)

		SBR  :  statement模式 ,以语句方式记录DML语句.会出现记录偏差;优点:节省空间 5.7版本之前
		MBR  :  Mixed 模式,混合模式.
		
mysql> select @@binlog_format;

(3) 内容格式
-- event: 
以event事件的方式记录所有的变化.binlog的最小记录单元为事件.
DDL DCL ,每条语句就是一个事件. 比如create创建一个表
DML ====> begin; A; ......  commit;	一个事务由多个事件构成.

-- event的结构: 
事件起始点:position 
事件内容.
结束点: end_position

上一个event的结束点就是下个event的起始点.是连续记录,不能出现断点.

2.3 查看二进制日志
--简单查看:
mysql> show binary logs;	#查看日志列表
mysql> flush logs;	#自动生成一个日志
mysql> show master status ;		#查看当前正在使用的日志信息

--事件查看:
show master status ;
show binlog events in 'mysql-bin.000004';	#详细查看日志
show binlog events in 'mysql-bin.000004' limit 5;	#详细查看日志5行
mysql -e "show binlog events in 'mysql-bin.000004'" |grep -C 5 "create"	#查看上下各5行内容
mysql -e "show binlog events in 'mysql-bin.000004'" |grep  "drop"	#过滤出drop相关的信息

--内容查看:
mysqlbinlog  /data/mysql/binlog_3306/mysql-bin.000004 |grep -v "SET"
查看日志更加详细的信息;主要针对行模式
mysqlbinlog  --base64-output=decode-rows -vvv /data/mysql/binlog_3306/mysql-bin.000004 |grep -v "SET"

2.4 使用二进制日志进行数据恢复【运维人员必备】
2.4.1 思路: 
 	1. 截取日志
     	起点: 
     	终点:
	2. 恢复日志 
   source /tmp/bin.sql
   
2.4.2 测试环境模拟故障并binlog恢复
   mysql> create database chengyin;
   mysql> use chengyin
   Database changed
   mysql> create table t1 (id int);
   mysql> insert into t1 values(1);
   mysql> commit;
   mysql> insert into t1 values(2);
   mysql> commit;
   mysql> insert into t1 values(3);
   mysql> commit;
   mysql> drop database chengyin;
   
   截取日志  
   mysql> show master status;
   mysql> show binlog events in 'mysql-bin.000010';
	1.查看起点: 
| mysql-bin.000010 |  259 | Query          |         6 |         365 | create database chengyin       
	2.终点:
| mysql-bin.000010 | 1384 | Query          |         6 |        1488 | drop database chengyin	

	3.截取日志
[root@db01 ~]# mysqlbinlog --start-position=259 --stop-position=1384 /data/mysql/binlog_3306/mysql-bin.000010 >/tmp/bin.sql 
[root@db01 ~]# mysqlbinlog --start-position=259 --stop-position=1384 -d world /data/mysql/binlog_3306/mysql-bin.000010 >/tmp/bin.sql  基于world库
[root@db01 ~]# mysqlbinlog --start-datetime=2004-12-25 --stop-datetime /data/mysql/binlog_3306/mysql-bin.000010 >/tmp/bin.sql 	#查询position号的时候会使用-datetime 模糊查找
	4.恢复日志 
set sql_log_bin=0;
source /tmp/bin.sql
set sql_log_bin=1;


2.4.3 日志滚动 
flush logs;		#通常在备份日志之前操作
重启数据库会进行滚动
mysql> select @@max_binlog_size;
+-------------------+
| @@max_binlog_size |
+-------------------+
|        1073741824 |
+-------------------+
1 row in set (0.00 sec)


2.4.4  binlog的删除
(1) 自动删除
select @@expire_logs_days;	#默认0,
在my.cnf配置文件中调整为15;
根据全备周期,至少全备周期+1,企业要求至少2*全备周期+1

(2) 手工删除
PURGE BINARY LOGS TO 'mysql-bin.000004'; #删除到11号为止,删除1-10
PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';	#按照时间删除

(3) 全部清空
reset master;	如果执行了这条命令,主从环境必崩

2.4.5 扩展-基于GTID的日志记录
(1) GTID 介绍
	5.6 版本的新特性,5.7进行了增强,建议开启.
	全局事务ID号.
特点: 对于每一个事务,都会有一个唯一性的编号.
	GTID具备幂等性,执行过的GTID的事务会自动跳过;和Ansible中的剧本那种效果差不多
	
(2) 开启GTID功能 
gtid-mode=on
enforce-gtid-consistency=true	

(3) 格式
	server_uuid:TID
mysql> create database xtz;
Query OK, 1 row affected (0.01 sec)

mysql> show master status ;
+------------------+----------+--------------+------------------+----------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000002 |      310 |              |                  | 411148c1-26bf-11ea-a420-000c298780da:1 |
+------------------+----------+--------------+------------------+----------------------------------------+

(4) 基于GTID的数据恢复
测试环境模拟数据和故障:
create database bgx;
use bgx
create table t1 (id int);
insert into t1 values(1);
commit;
insert into t1 values(2);
commit;
insert into t1 values(3);
commit;
drop database bgx;

恢复步骤: 
1.截取日志 
show master stauts;
mysql> show binlog events in 'mysql-bin.000002'
起点:
| mysql-bin.000002 |  310 | Gtid           |         6 |         375 | SET @@SESSION.GTID_NEXT= '411148c1-26bf-11ea-a420-000c298780da:2' |
| mysql-bin.000002 |  375 | Query          |         6 |         466 | create database bgx   

终点:
| mysql-bin.000002 | 1380 | Gtid           |         6 |        1445 | SET @@SESSION.GTID_NEXT= '411148c1-26bf-11ea-a420-000c298780da:7' |
| mysql-bin.000002 | 1445 | Query          |         6 |        1534 | drop database bgx   

mysqlbinlog --skip-gtids --include-gtids='411148c1-26bf-11ea-a420-000c298780da:2-6' /data/mysql/binlog_3306/mysql-bin.000002 >/tmp/gtid.sql
mysqlbinlog --skip-gtids --exclude-gtids='411148c1-26bf-11ea-a420-000c298780da:2-6' /data/mysql/binlog_3306/mysql-bin.000002 >/tmp/gtid.sql		#跳过gtid,相当于grep -v
mysqlbinlog --skip-gtids --include-gtids='411148c1-26bf-11ea-a420-000c298780da:2-6','..7-10' /data/mysql/binlog_3306/mysql-bin.000002 >/tmp/gtid.sql	多个gtid用法

2.恢复日志 
set sql_log_bin=0;
source /tmp/gtid.sql
set sql_log_bin=1;

3.验证查看数据是否正常恢复

注意: 开启GTID,可以有两种方式截取日志.但是都要在截取是加入--skip-gtids.
上次在我们公司生产环境出现了一次故障:
故障描述:日志截取恢复不了数据
故障背景:gtid模式下的binlog截取及恢复.
故障详述:我们公司刚上了5.7版本,对gitd这些新特性都不是很了解,,怎么做都恢复不了,把老大也着急了,全备是可以正常恢复的,日志截取怎么操作都恢复不成功,最后呢,我仔细研究了一下官方文档,看了一些新特性,新特性中提到截取日志时一定要加--skip-gtids参数,这个参数的意思是,在截取日志的时候,把gtid的信息全部抹掉,为什么要抹掉呢?因为gtid它本身具备幂等性的原则,系统里有gtid的话,就不会在恢复,加完这个参数之后,就可以正常恢复

3.慢日志

3.1 记录MySQL中较慢语句的日志.排查数据库语句问题的日志.
3.2 配置
mysql> show variables like '%slow%';	#查看慢日志参数
mysql> select @@long_query_time;	#默认慢查询时间;生产环境中调整为1s之内
mysql> select @@log_queries_not_using_indexes;	调整为1-->记录不走索引的语句,默认值为0,
vim /etc/my.cnf 
slow_query_log=ON 
slow_query_log_file=/data/mysql/data_3306/db01-slow.log
long_query_time=0.1
log_queries_not_using_indexes=1
先导入sql文件---->重启mysql服务---->慢日志才会生效

3.3 测试环境模拟慢语句
mysql> select * from t100w limit 10;
mysql> select * from t100w order by  k1 limit 10;
mysql> select * from t100w order by  k1 limit 10;
mysql> select * from t100w order by  k2 limit 10;
mysql> select * from t100w order by  k1,k2 limit 10;
mysql> select * from t100w order by  k1,k2,dt limit 10;
mysql> select * from t100w order by  k1,k2 desc  limit 10;
mysql> select k1 ,count(k2) from t100w  group by k1 order by count(k2) desc  limit 10;
mysql> select k1 ,count(k2) from t100w  group by k1 order by count(k2) desc  limit 10;
mysql> select k1 ,dt ,count(k2) from t100w  group by k1,dt order by count(k2) desc  limit 10;
mysql> select k1 ,dt ,count(k2) from t100w  group by k1,dt order by count(k2) desc  limit 10;
select a.k1 ,b.k2 ,b.dt from (select k1,k2 from t100w) a join (select k2,dt from t100w) b on a.k2=b.k2 order by a.k1 desc limit 10;

SQL优化:
alter table t100w add index idx(k2,k1);
alter table t100w add index idx_id(id);

再次测试:
select a.k1 ,b.k2 ,b.dt 
from (select k1,k2 from t100w where id<10) a 
join (select k2,dt from t100w where id<10) b 
on a.k2=b.k2 
order by a.k1 desc 
limit 10;

3.4 分析慢日志 
mysqldumpslow  -s c -t 3 db01-slow.log   
--select-->  看执行计划  --->  索引  ----> 语句
-s 排序的意思
看执行计划:desc select ......
若出现Using filesort时,原因是order by 出现了额外的排序操作--->针对相应的问题进行SQL语句优化

数据库慢分两种情况:   
	1. 应急性的  ------> show full processlist;
	2. 间歇性    ------> slow_log

还可以使用以下方式进行慢日志分析:
1. pt-query-digest 分析慢日志. 集成Anemometer进行图形化展示.
2. ELFK ---> slowlog

发布了148 篇原创文章 · 获赞 65 · 访问量 7629

猜你喜欢

转载自blog.csdn.net/chengyinwu/article/details/103724483