MySQL 日志管理

1. 错误日志

1.1 作用:

记录MySQL从启动以来,所有的状态、警告、错误。
为我们定位数据库问题,提供帮助。

1.2 配置方法

默认:开启状态,/datadir/hostname.err

mysql> select @@datadir;
+-------------+
| @@datadir   |
+-------------+
| /data/3306/ |
+-------------+
1 row in set (0.00 sec)

[root@master1 ~]# hostname
master1
  
[root@master1 ~]# ll /data/3306/master1.err 
-rw-r-----. 1 mysql mysql 54169 Aug  2 20:46 /data/3306/master1.err

定制方法:

vim /etc/my.cnf
log_error=/tmp/mysql.log
说明:日志目录必须得提前有,并且mysql有权限写入。
重启生效
# 判断数据库启动不了的方法,把信息打到屏幕上,可看到所有启动输出
[root@master ~]$ mysqld &

1.3 怎么看错误日志

[ERROR] 上下文

2. binlog二进制日志
2.1 作用:

主要记录数据库变化(DDL,DCL,DML)性质的日志。是逻辑层性质日志。
数据恢复,主从复制中应用

2.2 如何配置

默认:8.0版本以前,没有开启。我们建议生产开启。
配置方法:

vim /etc/my.cnf
server_id=6                  # 主机编号。主从中使用,5.7以后开binlog要加此参数
log_bin=/data/binlog/mysql-bin         # 日志存放目录+日志名前缀 例如:mysql-bin.000001
sync_binlog=1/0                # binlog日志刷盘策略,双一中的第二个1。每次事务提交立即刷写binlog到磁盘
binlog_format=row               # binlog的记录格式为row模式
expire_logs_days

说明:一定要和数据盘分开。 例如:
/dev/sdb --/data/3306 /dev/sdc --/data/binlog [root@db01 ~]$ mkdir -p /data/binlog [root@db01 ~]$ chown -R mysql:mysql /data/* [root@db01 ~]$ /etc/init.d/mysqld restart Shutting down MySQL.. SUCCESS! Starting MySQL. SUCCESS! [root@db01 ~]$ cd /data/binlog/ [root@db01 binlog]$ ll 总用量 12 -rw-r----- 1 mysql mysql 177 7月 14 19:42 mysql-bin.000001 -rw-r----- 1 mysql mysql 154 7月 14 19:42 mysql-bin.000002 -rw-r----- 1 mysql mysql 60 7月 14 19:42 mysql-bin.index

2.3 binlog记录内容详解
2.3.0 引入

binlog是SQL层的功能。记录的是变更SQL语句,不记录查询语句。

2.3.1 记录SQL语句种类

DDL :原封不动的记录当前DDL(statement语句方式)。
DCL :原封不动的记录当前DCL(statement语句方式)。
DML :只记录已经提交的事务DML(insert,update,delete)

2.3.2 DML三种记录方式

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

2.3.3 面试题

SBR与RBR模式的对比
STATEMENT  :可读性较高,日志量少,但是不够严谨
ROW      :可读性很低,日志量大,足够严谨
update t1 set xxx=xxx where id>1000 ? -->一共500w行,row模式怎么记录的日志
为什么row模式严谨?
id name intime
insert into t1 values(1,'zs',now())
我们建议使用:row记录模式

2.4 event(事件)是什么?
2.4.1 事件的简介

二进制日志的最小记录单元

对于DDL,DCL语句:一个语句就是一个event
对于DML语句来讲:只记录已提交的事务。
例如以下列子,就被分为了4个event
position 
        start   stop
begin;        120 - 340
DML1           340 - 460
DML2       460 - 550
commit;        550 - 760

2.4.2 event的组成

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

2.5 binlog的查看

2.5.1 查看开启情况

mysql> select @@log_bin;
mysql> select @@log_bin_basename;

2.5.2 文件查看

[root@db01 ~]$ ls -l /data/binlog
总用量 12
-rw-r----- 1 mysql mysql 177 7月 14 19:42 mysql-bin.000001
-rw-r----- 1 mysql mysql 154 7月 14 19:42 mysql-bin.000002
-rw-r----- 1 mysql mysql 60 7月 14 19:42 mysql-bin.index
[root@db01 ~]$ cat /data/binlog/mysql-bin.index 
/data/binlog/mysql-bin.000001
/data/binlog/mysql-bin.000002
[root@db01 ~]$ file /data/binlog/mysql-bin.000001
/data/binlog/mysql-bin.000001: MySQL replication log

2.5.3 二进制内置查看命令
(1)查看目前有几个日志文件

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

(2)查看当前在用的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)

(3)查看二进制日志事件

mysql> create database oldguo1 charset utf8mb4;
mysql> show binlog events in 'mysql-bin.000002';
mysql> grant all on *.* to root@'10.0.0.%' identified by 'mysql';
mysql> show binlog events in 'mysql-bin.000002';

mysql> use world
mysql> begin;
mysql> delete from city where id<10;
mysql> commit;
mysql> show binlog events in 'mysql-bin.000002';

====================================================================================
1. binlog 文件内容查看及数据恢复
1.1 事件查看
(1)

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.28-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids |         6 |         154 |                                       |
| mysql-bin.000001 | 154 | Stop           |         6 |         177 |                                       |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
3 rows in set (0.00 sec)
Log_name   :binlog文件名
Pos        :开始的position *****
Event_type :事件类型
Format_desc:格式描述,每一个日志文件的第一个事件,多用户没有意义,MySQL识别binlog必要信息
Server_id  :mysql服务号标识
End_log_pos:事件的结束位置号 *****
Info       :事件内容*****

补充:
SHOW BINLOG EVENTS
[IN 'log_name']
[FROM pos]
[LIMIT [offset,] row_count]

(2)

[root@db01 ~]$ mysql -uroot -pmysql -e "show binlog events in 'mysql-bin.000002'" | grep DROP

1.2 内容查看
(1)普通查看

[root@db01 ~]$ mysqlbinlog /data/binlog/mysql-bin.000002 >/tmp/a.sql
[root@db01 ~]$ vim /tmp/a.sql 
DDL:
# at 219
#200714 21:17:31 server id 6 end_log_pos 338
create database oldguo1 charset utf8mb4
# at 338
DML:
# at 690
BEGIN
# at 763
#200714 21:33:54 server id 6 end_log_pos 821
# at 821
#200714 21:33:54 server id 6 end_log_pos 1107
hg==
QrQNXyAGAAAAHgEAAFMEAAAAAGwAAAAAAAEAAgAF/+ACAAAAB29sZGdpcmwDQUZHCFFhbmRhaGFy
vJ8DAOADAAAAB29sZGdpcmwDQUZHBUhlcmF0sNkCAOAEAAAAB29sZGdpcmwDQUZHBUJhbGtoOPMB
AOAFAAAAB29sZGdpcmwDTkxEDU5vb3JkLUhvbGxhbmRAKAsA4AYAAAAHb2xkZ2lybANOTEQMWnVp
ZC1Ib2xsYW5kqQ0JAOAHAAAAB29sZGdpcmwDTkxEDFp1aWQtSG9sbGFuZES6BgDgCAAAAAdvbGRn
aXJsA05MRAdVdHJlY2h0U5MDAOAJAAAAB29sZGdpcmwDTkxEDU5vb3JkLUJyYWJhbnRzFAMA3Wvl
RA==
# at 1107
#200714 21:33:57 server id 6 end_log_pos 1138
COMMIT/*!*/;
# at 1138

(2)详细查看DML

[root@db01 ~]$ mysqlbinlog --base64-output=decode-rows -vvv /data/binlog/mysql-bin.000002 >/tmp/b.sql
[root@db01 ~]$ vim /tmp/b.sql
delete * from city where id<10;
### DELETE FROM `world`.`city`
### WHERE
### @1=3 /* INT meta=0 nullable=0 is_null=0 */
### @2='oldgirl' /* STRING(140) meta=65164 nullable=0 is_null=0 */
### @3='AFG' /* STRING(12) meta=65036 nullable=0 is_null=0 */
### @4='Herat' /* STRING(80) meta=65104 nullable=0 is_null=0 */
### @5=186800 /* INT meta=0 nullable=0 is_null=0 */

(3)查看参数

[root@db01 ~]$ mysqlbinlog --help
  --base64-output=name 
                      Determine when the output statements should be
                      base64-encoded BINLOG statements: 'never' disables it and
                      works only for binlogs without row-based events;
                      'decode-rows' decodes row events into commented
                      pseudo-SQL statements if the --verbose option is also
                      given; 'auto' prints base64 only when necessary (i.e.,
                      for row-based events and format description events).  If
                      no --base64-output[=name] option is given at all, the
                      default is 'auto'.

1.3 日志截取恢复
日志恢复案例:

1)刷新出一个新的binlog文件/滚动一个新的日志 ----》flush logs
mysql> show binary logs;
mysql> flush logs;
mysql> show binary logs;

2)模拟数据环境: mysql> show binary logs; mysql> create database bindb charset utf8mb4; mysql> use bindb mysql> create table t1(id int); mysql> begin; mysql> insert into t1 values(1),(2),(3); mysql> commit; mysql> begin; mysql> insert into t1 values(11),(22),(33); mysql> commit; mysql> begin; mysql> insert into t1 values(111),(222),(333); mysql> commit; mysql> select * from t1; mysql> drop database bindb; mysql> show databases; (3)数据恢复 分析binlog 起点: mysql> show master status; mysql> show binlog events in 'mysql-bin.000003'; | 219 | 332 | create database bindb charset utf8mb4 | 终点: | 1356 | 1451 | drop database bindb | 截取日志 [root@db01 ~]$ mysqlbinlog --start-position=219 --stop-position=1356 /data/binlog/mysql-bin.000003 >/tmp/bin.sql; 恢复日志 mysql> set sql_log_bin=0; mysql> source /tmp/bin.sql mysql> set sql_log_bin=1; 验证数据 mysql> show databases; mysql> use bindb; mysql> select * from t1; 或 mysql> select * from bindb.t1;

思考一个问题:如果是生产环境中,此种恢复手段会有什么弊端?

1. binlog记录不单单一个数据库的操作,可能对其他数据库重复操作?
mysqlbinlog -d bindb --start-position=219 --stop-position=1356 /data/binlog/mysql-bin.000003 >/tmp/bin.sql;

2. 需要的日志在多个文件中分布
起点:加入在1号文件,假如,mysql-bin.000001,    4600
终点:一般是最后一个文件,假如,mysql-bin.000002,    980
mysqlbinlog --start-datetime= --stop-datetime=1356 /data/binlog/mysql-bin.000001 /data/binlog/mysql-bin.000002 >/tmp/bin.sql;

3. 创建了几年,期间一直在用的数据库,插入数据的操作从bin_log。000001到bin_log。000001234之中都有的库,被删除了,怎么恢复?
4. 数据多了咋办,数据行多?
假设:每周六做全备份23:00,binlog每天备份23:00。
故障点 周三 10点 drop操作

binlog实际上是我们数据恢复是配合备份一起恢复数据的手段。

==============================================================
2. binlog 维护操作
2.1 日志滚动

1)mysql> flush logs;
(2)mysql> select @@max_binlog_size;
(3)[root@db01 ~]$ mysqladmin -uroot -pmysql fulsh-logs
(4)[root@db01 binlog]$ mysqldump -F
(5)重启数据库自动滚动
以上为日志触发情景。

2.2 日志的删除

注意:不要使用rm命令删除日志。

2.2.1 自动删除机制

mysql> select @@expire_logs_days;
默认是0,单位是天,代表永不删除。
问题: 到底设置多少天合适?阈值?
一个全备份周期。7+1天一般生产一般建议,最少2个全备周期+1

2.2.2 手工删除

mysql> help purge;
mysql> help purge binary logs;
Examples:
PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2019-04-02 22:46:26';

mysql> show binary logs;
mysql> purge binary logs to 'mysql-bin.000006';
mysql> show binary logs;

2.2.3 全部清空

mysql> reset master;
比较危险,在主库执行此操作,主从必宕。

======================================================================
3. binlog的GTID模式管理

3.1 GTID 介绍

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

3.2 GTID(Global Transaction ID)

是对于一个已提交事务的编号,并且是一个全局唯一的编号。
它的官方定义如下:

GTID = server_uuid :transaction_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29

3.3 重要参数介绍:

vim /etc/my.cnf
gtid-mode=on
enforce-gtid-consistency=true
DDL:
mysql> select @@gtid_mode;
mysql> show master status;
mysql> create database gtid_text;
mysql> show master status;
mysql> show binlog events in 'mysql-bin.000002';
mysql> create database gtid_text1;
mysql> show binlog events in 'mysql-bin.000002';
mysql> create database gtid_text2;
mysql> show binlog events in 'mysql-bin.000002';
mysql> select @@server_uuid;
DML:(事务)
mysql> begin;
mysql> use world
mysql> delete from city where id=1;
mysql> commit;
mysql> show binlog events in 'mysql-bin.000002';

3.4 基于GTID进行查看binlog

具备GTID后,截取查看某些事务日志:
--include-gtids
--exclude-gtids

mysqlbinlog --skip-gtids --include-gtids='066d65da-b0a8-11ea-affd-000c29682dd4:5-11' mysql-bin.000002 mysql-bin.000003 mysql-bin.000004 >/tmp/gtdb1.sql
mysqlbinlog --skip-gtids --include-gtids='dff98809-55c3-11e9-a58b-000c2928f5dd:1-6' --exclude-gtids='dff98809-55c3-11e9-a58b-000c2928f5dd:4' /data/binlog/mysql-bin.000004

例子:(跨多文件的)

# 第一波命令
mysql> show master status;
mysql> create database gtdb charset utf8mb4;
mysql> use gtdb
mysql> create table t1(id int);
mysql> begin;
mysql> insert into t1 values(1),(2),(3);
mysql> commit;
mysql> flush logs;
mysql> show master status;

# 第二波命令
mysql> create table t2(id int);
mysql> begin;
mysql> insert into t2 values(1),(2),(3);
mysql> commit;
mysql> flush logs;
mysql> show master status;

# 第三波命令
mysql> create table t3(id int);
mysql> begin;
mysql> insert into t3 values(1),(2),(3);
mysql> commit;
mysql> show master status;
mysql> drop database gtdb;

# 截取日志
起点:
mysql> show binlog events in 'mysql-bin.000002';
++++++++++++++++++++++++++++++++++++++++++++++++
SET @@SESSION.GTID_NEXT= '066d65da-b0a8-11ea-affd-000c29682dd4:5' |
create database gtdb charset utf8mb4 
++++++++++++++++++++++++++++++++++++++++++++++++
终点:
mysql> show master status;
mysql> show binlog events in 'mysql-bin.000004';
++++++++++++++++++++++++++++++++++++++++++++++++
SET @@SESSION.GTID_NEXT= '066d65da-b0a8-11ea-affd-000c29682dd4:12' |
drop database gtdb 
++++++++++++++++++++++++++++++++++++++++++++++++
得出结果:
gtid:5-11
文件:mysql-bin.000002 mysql-bin.000003 mysql-bin.000004
# 截取:
[root@db01 ~]$ cd /data/binlog/
[root@db01 binlog]$ mysqlbinlog --include-gtids='066d65da-b0a8-11ea-affd-000c29682dd4:5-11' mysql-bin.000002 mysql-bin.000003 mysql-bin.000004 >/tmp/gtdb.sql

mysql> set sql_log_bin=0;
mysql> source /tmp/gtdb.sql
mysql> show databases;
未成功

3.5 GTID的幂等性

开启GTID后,MySQL恢复Binlog时,重复GTID的事务不会再执行了
就想恢复?怎么办?
--skip-gtids

[root@db01 binlog]$ mysqlbinlog --skip-gtids --include-gtids='066d65da-b0a8-11ea-affd-000c29682dd4:5-11' mysql-bin.000002 mysql-bin.000003 mysql-bin.000004 >/tmp/gtdb1.sql
[root@db01 binlog]$ vimdiff /tmp/gtdb.sql /tmp/gtdb1.sql 
mysql> set sql_log_bin=0;
mysql> source /tmp/gtdb1.sql
mysql> set sql_log_bin=1;

mysql> show databases;
mysql> use gtdb
mysql> show tables;
mysql> select * from t1;
mysql> select * from t2;
mysql> select * from t3;
成功!

3.6 查看server_uuid

[root@db01 ~]$ cat /data/3306/auto.cnf
[auto]
server-uuid=066d65da-b0a8-11ea-affd-000c29682dd4
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 066d65da-b0a8-11ea-affd-000c29682dd4 |
+--------------------------------------+
1 row in set (0.00 sec)

4. slowlog 慢日志

4.1 作用:

记录MySQL运行过程中较慢的语句,通过一个文本的文件记录下来。

帮助我们进行语句优化工具日志。

4.2 如何配置

默认慢日志没有开启。
配置参数:

mysql> select @@slow_query_log;    # 是否开启
mysql> select @@slow_query_log_file;    # 文件存放位置
mysql> select @@long_query_time;    # 慢语句评估/认定时间阈值
mysql> select @@log_queries_not_using_indexes;    # 不走索引的语句也记录
vim /etc/my.cnf
slow_query_log=1
slow_query_log_file=/data/3306/db01-slow.log
long_query_time=0.1
log_queries_not_using_indexes=1
重启数据库生效。
[root@db01 ~]$ cd /data/3306
-rw-r----- 1 mysql mysql 187 7月 15 09:08 db01-slow.log

4.3 模拟慢语句(t100w表)

mysql> set sql_log_bin=0;
mysql> source /root/t100w.sql
mysql> set sql_log_bin=1;

[root@db01 ~]$ cd /data/3306
[root@db01 3306]$ > db01-slow.log 
-rw-r----- 1 mysql mysql 0 7月 15 09:16 db01-slow.log
select * from t100w limit 500000,10;
select * from t100w limit 600000,10;
select * from t100w limit 600000,1;
select * from t100w limit 600000,2;
select id,count(num) from t100w group by id limit 10;
select id,count(num) from t100w group by id limit 5;
select id,count(num) from t100w group by id limit 2;
select id,count(num) from t100w group by id limit 2;
select id,count(k1) from t100w group by id limit 1;
select id,count(k2) from t100w group by id limit 1;
select k2,sum(id) from t100w group by k2 limit 1;
select k2,sum(id) from t100w group by k2,k1 limit 1;
select k2,sum(id) from t100w group by k2,k1 limit 1;
select k1,sum(id) from t100w group by k2,k1 limit 1;
select k1,count(id) from t100w group by k1 limit 10;

4.4 慢语句分析

[root@db01 3306]$ vim db01-slow.log 
[root@db01 3306]$ mysqldumpslow -s c -t 5 /data/3306/db01-slow.log 
Reading mysql slow query log from /data/3306/db01-slow.log
Count: 4 Time=0.29s (1s) Lock=0.00s (0s) Rows=5.8 (23), root[root]@localhost
select * from t100w limit N,N
Count: 4 Time=3.51s (14s) Lock=0.00s (0s) Rows=4.8 (19), root[root]@localhost
select id,count(num) from t100w group by id limit N
Count: 2 Time=1.91s (3s) Lock=0.00s (0s) Rows=1.0 (2), root[root]@localhost
select k2,sum(id) from t100w group by k2,k1 limit N
Count: 1 Time=3.07s (3s) Lock=0.00s (0s) Rows=1.0 (1), root[root]@localhost
select id,count(k2) from t100w group by id limit N
Count: 1 Time=1.90s (1s) Lock=0.00s (0s) Rows=1.0 (1), root[root]@localhost
select k1,sum(id) from t100w group by k2,k1 limit N

4.5 课后作业

自己扩展:可视化展示 slow-log

 pt-query-digest + Amemometer

posted @ 2020-08-02 19:16  丁海龙  阅读(182)  评论(0)    收藏  举报