专职DBA-MySQL日志管理2

时间:2021-10-15 04:58:17

专职DBA-MySQL日志管理2

专职DBA-MySQL日志管理2

[[email protected] ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf &
[[email protected] ~]# ps -ef | grep mysql
[[email protected] ~]# netstat -lnp | grep mysql
[[email protected] ~]# mysql -S /data/mysql/3306/mysql.sock -p


错误日志(log_error): 文本形式记录MySQL启动,关闭,日常运行过程中所有状态信息,警告,错误。
错误日志配置,默认就是开启的:/数据目录下/hostname.err
手工设定:
mysql> select @@log_error;
 ---------------------------- 
| @@log_error                |
 ---------------------------- 
| /data/mysql/3306/error.log |
 ---------------------------- 
1 row in set (0.01 sec)

mysql> show global variables like "log_error";

[[email protected] ~]# grep "log_error" /data/mysql/3306/my.cnf
log_error = /data/mysql/3306/error.log # /usr/local/mysql/data/localhost.localdomain.err
log_timestamps = system


日志内容查看,主要关注[ERROR]看上下文
[[email protected] ~]# grep "ERROR" /data/mysql/3306/error.log


binlog(binary logs) 二进制日志
二进制形式,记录MySQL工作过程中,所有变更类(除了select和show)的操作日志。
可以理解为记录的是SQL语句,逻辑性质日志。
(1).数据恢复  备份恢复必须依赖binlog日志。
(2).主从复制  主从环境必须依赖binlog日志。

binlog配置 (5.7必须加server_id)
注意:MySQL默认是没有开启二进制日志的。
基础参数查看:
mysql> show global variables like "%log_bin%";
mysql> show global variables like "%binlog%";

开关
mysql> select @@log_bin;
 ----------- 
| @@log_bin |
 ----------- 
|         1 |
 ----------- 
1 row in set (0.00 sec)

日志路径及名字
mysql> select @@log_bin_basename;
 --------------------------------- 
| @@log_bin_basename              |
 --------------------------------- 
| /data/mysql/3306/logs/mysql-bin |
 --------------------------------- 
1 row in set (0.00 sec)

服务ID号
mysql> select @@server_id;
 ------------- 
| @@server_id |
 ------------- 
|      113306 |
 ------------- 
1 row in set (0.00 sec)

二进制日志格式
mysql> select @@binlog_format;
 ----------------- 
| @@binlog_format |
 ----------------- 
| ROW             |
 ----------------- 
1 row in set (0.00 sec)

双一标准之二:
mysql> select @@sync_binlog;
 --------------- 
| @@sync_binlog |
 --------------- 
|             1 |
 --------------- 
1 row in set (0.00 sec)


my.cnf配置文件
[[email protected] ~]# vim /data/mysql/3306/my.cnf
server_id = 113306
log_bin = /data/mysql/3306/logs/mysql-bin       # off
binlog_format = row
sync_binlog = 1  #双1标准,每次事务提交立即刷写binlog


参数说明
server_id=113306
主要是在主从复制过程中必须要加的,但是在5.7版本中,要用以下参数(log_bin),开启binlog日志,即使是单机也是必加的。
log_bin = /data/mysql/3306/logs/mysql-bin
(1).开启二进制日志功能。
(2).设置二进制日志目录及名称前缀
binlog_format = row
binlog的记录格式??
binlog记录了什么?
binlog是SQL层的功能。记录的是变更SQL语句,不记录查询语句。

记录SQL语句种类
DDL原封不动的记录当前DDL(statement语句方式)。
DCL原封不动的记录当前DCL(statement语句方式)。
DML只记录已经提交的事务DML.


DML三种记录方式
binlog_format(binlog的记录格式)参数影响
(1).statement(5.6默认) SBR(statement based replication) 语句模式原封不动的记录当前DML的SQL语句本身。
(2).ROW(5.7 默认值) RBR(ROW based replication) 记录数据行的变化(用户看不懂,需要工具分析)
(3).mixed(混合)MBR (mixed based replication) 以上两种模式的混合。

记录模式:
STATEMENT(SBR): 语句模式 ,记录的就是SQL语句本身.
ROW      (RBR): 行模式, 记录的是数据行的变化.
Mixed    (MBR): 混合模式,自动判断用什么模式存储日志.
我们的建议是:row(> = 5.7.7 默认ROW)

面试题:
SBR与RBR模式的对比:
STATEMENT:可读性较高,日志量少,但是不够严谨。
ROW:可读性很低,日志量大,足够严谨。
update t1 set xxx=xxx where id>1000   ? -->一共500w行,row模式怎么记录的日志
为什么row模式严谨?
id  name    intime
insert into t1 values(1,zhang3,now());
我们建议使用:row记录模式。
MySQL一些新特性, 必须要基于ROW模式,GTID,GC MTS



event(事件)是什么?
事件的简介:binlog记录的最小单元。
对于DDL,DCL,一个语句就是一个event。
对于DML语句来讲,只记录已提交的事务。
start  position (文件中的相对位置号)  开始位置
事件内容: DDL  DCL   DML 
stop   position (文件中的相对位置号)  结束位置
例如以下列子,就被分为了4个event
begin;      120  - 340
DML1        340  - 460
DML2        460  - 550
commit;     550  - 760


event的组成
三部分构成:
(1).事件的开始标识
(2).事件内容
(3).事件的结束标识
Position:
开始标识: at 194
结束标识: end_log_pos 254
194? 254?
某个事件在binlog中的相对位置号。位置号的作用是什么?为了方便我们截取事件。


日志文件查看
查看日志的开启情况
log_bin参数设置的路径,可以找到二进制日志。
mysql> show variables like "%log_bin%";
 --------------------------------- --------------------------------------- 
| Variable_name                   | Value                                 |
 --------------------------------- --------------------------------------- 
| log_bin                         | ON                                    |
| log_bin_basename                | /data/mysql/3306/logs/mysql-bin       |
| log_bin_index                   | /data/mysql/3306/logs/mysql-bin.index |
| log_bin_trust_function_creators | OFF                                   |
| log_bin_use_v1_row_events       | OFF                                   |
| sql_log_bin                     | ON                                    |
 --------------------------------- --------------------------------------- 
6 rows in set (0.00 sec)


查看一共多少个binlog
mysql> show binary logs;
 ------------------ ----------- 
| Log_name         | File_size |
 ------------------ ----------- 
| mysql-bin.000001 |       154 |
 ------------------ ----------- 
1 row in set (0.00 sec)

mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)

mysql> show binary logs;
 ------------------ ----------- 
| Log_name         | File_size |
 ------------------ ----------- 
| mysql-bin.000001 |       201 |
| mysql-bin.000002 |       154 |
 ------------------ ----------- 
2 rows in set (0.00 sec)


查看mysql正在使用的binlog日志文件
mysql> show master status;
 ------------------ ---------- -------------- ------------------ ------------------- 
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
 ------------------ ---------- -------------- ------------------ ------------------- 
| mysql-bin.000002 |      154 |              |                  |                   |
 ------------------ ---------- -------------- ------------------ ------------------- 
1 row in set (0.00 sec)
File:当前MySQL正在使用的文件名
Position:最后一个事件的结束位置号



查看binlog事件信息
mysql> show binlog events in mysql-bin.000002;
 ------------------ ----- ---------------- ----------- ------------- --------------------------------------- 
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
 ------------------ ----- ---------------- ----------- ------------- --------------------------------------- 
| mysql-bin.000002 |   4 | Format_desc    |    113306 |         123 | Server ver: 5.7.26-log, Binlog ver: 4 |
| mysql-bin.000002 | 123 | Previous_gtids |    113306 |         154 |                                       |
 ------------------ ----- ---------------- ----------- ------------- --------------------------------------- 
2 rows in set (0.00 sec)


Log_name:binlog文件名
Pos:事件开始的位置点position
Event_type:事件类型
Format_desc:格式描述,每一个日志文件的第一个事件,多用户没有意义,MySQL识别binlog必要信息
Server_id:mysql服务号标识
End_log_pos:事件的结束位置点position
Info:事件内容

mysql> help show binlog events;
Name: SHOW BINLOG EVENTS
Description:
Syntax:
SHOW BINLOG EVENTS
   [IN ‘log_name‘]
   [FROM pos]
   [LIMIT [offset,] row_count]

[[email protected] ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show binlog events in mysql-bin.000002;" | grep drop


binlog文件内容详细查看
[[email protected] ~]# mysqlbinlog /data/mysql/3306/logs/mysql-bin.000002
[[email protected] ~]# mysqlbinlog --base64-output=decode-rows -vvv /data/mysql/3306/logs/mysql-bin.000002
[[email protected] ~]# mysqlbinlog -d school /data/mysql/3306/logs/mysql-bin.000002
[[email protected] ~]# mysqlbinlog --start-datetime=‘2019-05-06 17:00:00‘ --stop-datetime=‘2019-05-06 17:01:00‘ /data/mysql/3306/logs/mysql-bin.000002


基于Position号进行日志截取
核心就是找截取的起点和终点
--start-position=219
--stop-position=512
[[email protected] ~]# mysqlbinlog --start-position=219 --stop-position=512 /data/mysql/3306/logs/mysql-bin.000002 >/tmp/bin.sql

案例:使用binlog日志进行数据恢复
模拟
mysql> create database binlog charset=utf8mb4;
mysql> use binlog;
mysql> create table t1(id int);
mysql> insert into t1 values(1);
mysql> commit;
mysql> insert into t1 values(2);
mysql> commit;
mysql> drop database binlog;

恢复
mysql> show master status;
mysql> show binlog events in mysql-bin.000002;
[[email protected] ~]# mysqlbinlog --skip-gtids --start-position=219 --stop-position=1176 /data/mysql/3306/logs/mysql-bin.000002 >/tmp/bin.sql
[[email protected] ~]# mysql -S /data/mysql/3306/mysql.sock -p
mysql> set sql_log_bin=0;
mysql> source /tmp/bin.sql;
mysql> set sql_log_bin=1;

面试案例:
1.备份策略每天全备,有全量的二进制日志。
2.业务中一共10个库,其中一个被误drop了。
3.需要在其他9个库正常工作过程中进行数据恢复。

补充:
200G每天(23:00)全备,每天备份binlog,周三上午10误删的表t1.
恢复思路:
1.停业务,挂维护页.
2.找临时库,恢复全备.
3.截取全备之后,一直到删表之前的所有binlog
4.导出表,导入到生产.


binlog日志的GTID新特性。
GTID 介绍
5.6版本新加的特性,5.7中做了加强。
5.6中不开启,没有这个功能。
5.7中的GTID即使不开也会有自动生成。
SET @@SESSION.GTID_NEXT= ANONYMOUS


GTID(Global Transaction ID) (MySQL5.6.9版本)
是对于一个已提交事务的编号,并且是一个全局唯一的编号。每次累加数字。
在传统模式的基础上,加入对于每个事务唯一的编号. 
DDL,DCL ,一条语句就是一个事务.会分配一个唯一的GTID号码 
DML, begin;xxx;commit作为一个完整的事务,分配一个唯一的GTID号
这些号码,唯一的,连续的,具备幂等性的.
它的官方定义如下:
GTID = source_id:transaction_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29

mysql> select @@server_uuid;
 -------------------------------------- 
| @@server_uuid                        |
 -------------------------------------- 
| 6f02ba92-d1b7-11e9-bf6f-000c29ca1344 |
 -------------------------------------- 
1 row in set (0.00 sec)

mysql> show global variables like %gtid%;
mysql> show variables like %gtid%;

重要参数介绍:
[[email protected] ~]# vim /data/mysql/3306/my.cnf
gtid_mode = on
enforce_gtid_consistency = on


create database gtid charset utf8mb4;
use gtid
create table t1(id int);
create table t2(id int);
create table t3(id int);
begin;
insert into t1 values(1);
commit;
begin;
insert into t2 values(1);
commit;

mysql> show master status;



基于GTID进行查看binlog
具备GTID后,截取查看某些事务日志:
--include-gtids 包含
--exclude-gtids 排除
[[email protected] ~]# mysqlbinlog --include-gtids=‘dff98809-55c3-11e9-a58b-000c2928f5dd:1-6‘ --exclude-gtids=‘dff98809-55c3-11e9-a58b-000c2928f5dd:5‘ /data/mysql/3306/logs/mysql-bin.000002


GTID的幂等性:开启GTID后,MySQL恢复Binlog时,重复GTID的事务不会再执行了。
就想恢复?怎么办?
--skip-gtids
[[email protected] ~]# mysqlbinlog --skip-gtids --include-gtids=‘dff98809-55c3-11e9-a58b-000c2928f5dd:1-6‘ --exclude-gtids=‘dff98809-55c3-11e9-a58b-000c2928f5dd:5‘ /data/mysql/3306/logs/mysql-bin.000002 > /tmp/1.sql
set sql_log_bin=0;
source /tmp/binlog.sql
set sql_log_bin=1;
结论:在开启GTID模式的binlog截取时,都要加--skip-gtids.

使用二进制日志恢复数据案例
故障环境介绍
创建了一个库db,导入了表t1,t1表中录入了很多数据。
一个开发人员,drop database db;
没有备份,日志都在,怎么恢复?
思路:找到建库语句到删库之前所有的日志,进行恢复(开启了GTID模式)
故障案例模拟:
drop database if exists db;
create database db charset utf8mb4;     
use db;
create table t1(id int);
insert into t1 values(1),(2),(3);
insert into t1 values(4),(5),(6);
commit
update t1 set id=30 where id=3;
commit;
delete from t1 where id=4;
commit;
insert into t1 values(7),(8),(9);
commit;
drop database db;
=============================================
运行以上语句,模拟故障场景
需求:将数据库恢复到以下状态(提示第10步和第14步是误操作,其他都是正常操作)


恢复过程(无GTID时的恢复)
查看当前使用的 binlog文件
mysql> show master status;
查看事件
mysql> show binlog events in mysql-bin.000002;
截取第一段
[[email protected] ~]# mysqlbinlog --start-position=219 --stop-position=512 /data/mysql/3306/logs/mysql-bin.000002 >/tmp/bin1.sql
截取第二段
[[email protected] ~]# mysqlbinlog --start-position=768 --stop-position=1025 /data/mysql/3306/logs/mysql-bin.000002 >/tmp/bin2.sql

恢复
mysql> set sql_log_bin=0;
mysql> source /tmp/bin1.sql
mysql> source /tmp/bin2.sql
mysql> set sql_log_bin=1;
mysql> select * from t1;


有GTID的截取
mysqlbinlog --skip-gtids --include-gtids=‘dff98809-55c3-11e9-a58b-000c2928f5dd:1-18‘ --exclude-gtids=‘dff98809-55c3-11e9-a58b-000c2928f5dd:9‘ /data/mysql/3306/logs/mysql-bin.000002 > /tmp/bin3.sql


恢复
mysql> set sql_log_bin=0;
mysql> source /tmp/bin3.sql
mysql> set sql_log_bin=1;
mysql> select * from t1;



二进制日志其他操作
自动清理日志,binlog删除,什么时候可以删除binlog?
保证有一份可用的全备.看全备周期.
自动清理:
mysql> show global variables like "%days%";
 ------------------ ------- 
| Variable_name    | Value |
 ------------------ ------- 
| expire_logs_days | 7     |
 ------------------ ------- 
1 row in set (0.00 sec)

自动清理时间,是要按照全备周期 1
mysql> set global expire_logs_days=8;

永久生效写入配置文件/data/mysql/3306/my.cnf
expire_logs_days = 15
企业建议至少保留两个全备周期 1天的binlog
7 7 1=15

手工清理
PURGE BINARY LOGS BEFORE now() - INTERVAL 3 day;
PURGE BINARY LOGS BEFORE 2008-04-02 22:46:26;
PURGE BINARY LOGS TO mysql-bin.000010;
注意:不要手工rm -rf binlog文件
1.my.cnf  binlog关闭掉,启动数据库。
2.把数据库关闭,开启binlog,启动数据库。
删除所有binlog,并从000001开始重新记录日志。

mysql> reset master; 主从关系中,主库执行此操作,主从环境必崩。


binlog文件是怎么滚动切割
1.flush logs;
2.重启mysql也会自动滚动一个新的。
3.日志文件达到1G大小(max_binlog_size)
mysql> show global variables like "%binlog_size%";
 ----------------- ------------ 
| Variable_name   | Value      |
 ----------------- ------------ 
| max_binlog_size | 1073741824 |
 ----------------- ------------ 
1 row in set (0.00 sec)
4.数据备份时加入参数也可以自动滚动



slow_log 慢日志
以文本格式追加记录慢SQL语句的日志,定位低效SQL语句的工具日志。
辅助我们排查SQL性能问题的工具日志.
mysql> show variables like %slow%;
mysql> show variables like %index%;

slow_query_log = on                                    # off
slow_query_log_file = /data/mysql/3306/slow.log             # hostname.log

开启慢日志(默认没开启) /data/mysql/3306/my.cnf
开关
slow_query_log = on                                    # off

文件位置及名字
slow_query_log_file = /data/mysql/3306/slow.log             # hostname.log

设定慢查询时间
long_query_time=0.1

没走索引的语句也记录
log_queries_not_using_indexes=on



mysqldumpslow 分析慢日志
[[email protected] ~]# mysqldumpslow -s c -t 3 /data/mysql/3306/slow.log

第三方分析工具(自己扩展)
https://www.percona.com/downloads/percona-toolkit/LATEST/
[[email protected] ~]# yum install perl-DBI perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL perl-Digest-MD5

percona-toolkit工具包中的命令:
[[email protected] ~]# pt-query-diagest /data/mysql/3306/slow.log

还有一个是Anemometer基于pt-query-digest将MySQL慢查询可视化

推荐分析工具:
pt-digest   Anemometer
ELK