[mysql] 日志管理

124 阅读6分钟

一、前言

日志是记录我们系统运行的点点滴滴,mysql有log_error(错误日志) ,binlog(二进制日志),show_log(慢日志),redo log(重做日志),undo log(回滚日志),relay log(中继日志),general log(一般日志);其中redo log 和 undo log用于数据库事务,binlog 和 relay log用于主从复制;这次我们主要讲 log_error,binlog以及show_log。

二、错误日志

记录mysql从启动以来所有的状态,警告,错误,我们可以通过错误日志来排查问题。

系统是默认开启的,存放路径我们可从

mysql> SELECT @@datadir;
+-----------------+
| @@datadir       |
+-----------------+
| /var/lib/mysql/ |
+-----------------+
1 row in set (0.00 sec)

我们也可以在配置文件中社设置错误日志的路径

#在配置文件中设置日志目录
log_error=/tmp/mysql.log

三、binlog二进制日志

主要记录数据库数据变化的日志,DDL,DCL,DML。其中DDL和DCL都是原封不动记录,DML只记录已提交的事务语句。所以呢可以用来数据恢复,主从复制。8.0版本以前默认没有开启,所以我们要手动开启,注意:一定要和数据盘分开,不然一旦数据盘损坏,binlog又没有,那就恢复不了,

如:

/dev/sdb -----> 数据盘

/dev/sdc ------>日志盘

3.1binlog基础

查询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/mysql-bin |
+-----------------------+
1 row in set (0.00 sec)

开启binlog 配置文件

#主机编号
server_id=8001
#日志存放目录  路径要存在,并且有权限 mysql-bin 是前缀 生成mysql-bin.000001
log_bin=/data/mysql/mysql-bin
# binlog日志刷盘策略 每次事务提交立即刷到binlog磁盘
sync_binlog=1
#binlog日志格式
binlog_format=row 

参数说明:

binlog_format:

1): statement(SBR): 语句原封不动的记录 。如sql,日志量少,可读性高,不够严谨 。

2):ROW(RBR):记录行变化数据,需要工具解析。可读性低,日志量大,足够严谨。

3):mixed(MBR) 以上两种的混合

比如

我们插入 update t_user set name = "" where id >200

statement 因为原封不动记录sql 所以日志量少,而row模式就得记录id大于200以上的行数据变化,所以日志量就比较大,可读性高;

但我们插入如 insert into t_user value("张三",now()) 这是如果系统崩了,我们重新恢复日志,那么 now()的时间就不准确了。

总结: 有人喜欢用 row 有人喜欢用 mixed 看个人吧

event(事件):二进制日志的最小单元;它是由时间 开始标识、事件内容、事件结束标识

列如:

position start stop

begin; 120 - 340

DML1 340 - 460

DML2 460 - 550

commit; 550 - 760

查看目前的日志文件列表

mysql> show binary logs;
+------------------+-----------+-----------+
| Log_name         | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000003 |      4859 | No        |
| mysql-bin.000004 |       155 | No        |
+------------------+-----------+-----------+
2 rows in set (0.00 sec)

查看当前在用的日志文件

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |      155 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

查看事件内容

mysql> show binlog events in 'mysql-bin.000004';

如何查看二进制文件

使用mysqlbinlog将binlog文件导出

mysqlbinlog  /data/mysql/mysql-bin.000003 >/tmp/mysql-bin.log

然后打开分析:

# at 1446
#200416  5:05:32 server id 8001  end_log_pos 1552 CRC32 0x70ab07aa      Query   thread_id=10    exec_time=0     error_code=0    Xid = 1210
SET TIMESTAMP=1587013532/*!*/;
SET @@session.foreign_key_checks=1/*!*/;
DROP DATABASE `test`
/*!*/;
# at 1552
#200416  5:05:38 server id 8001  end_log_pos 1631 CRC32 0x48cccba6      Anonymous_GTID  last_committed=4        sequence_number=5       rbr_only=no     original_committed_timestamp=1587013539019004     immediate_commit_timestamp=1587013539019004     transaction_length=616
# original_commit_timestamp=1587013539019004 (2020-04-16 05:05:39.019004 UTC)
# immediate_commit_timestamp=1587013539019004 (2020-04-16 05:05:39.019004 UTC)
/*!80001 SET @@session.original_commit_timestamp=1587013539019004*//*!*/;
/*!80014 SET @@session.original_server_version=80019*//*!*/;
/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3769
#200416  7:18:18 server id 8001  end_log_pos 3851 CRC32 0x4e849f3d      Query   thread_id=33    exec_time=23    error_code=0
SET TIMESTAMP=1587021498/*!*/;
BEGIN
/*!*/;
# at 3851
#200416  7:18:18 server id 8001  end_log_pos 3983 CRC32 0xda7b1b80      Query   thread_id=33    exec_time=23    error_code=0
SET TIMESTAMP=1587021498/*!*/;
INSERT INTO `neti`.`test`(`id`, `test`) VALUES (1, '1')
/*!*/;
# at 3983
#200416  7:18:18 server id 8001  end_log_pos 4014 CRC32 0xdd680a7c      Xid = 2250
COMMIT/*!*/;

3.2binlog维护工作:

3.2.1:日志滚动

1):命令行

mysql> flush logs;

2):日志量达到值重新生成binlog文件

mysql> select @@max_binlog_size;
+-------------------+
| @@max_binlog_size |
+-------------------+
|        1073741824 |
+-------------------+
1 row in set (0.00 sec)

3):重启数据库

3.2.2:日志删除

注意,不要直接用rm这种暴力手段来删除文件 应该使用命令行来清理

1):自动清理

默认为0,单位是天,代表不删除。我们一般根据全备周期来设置;当然生产环境预留两个全备周期会比较好。这样一旦其中一个全备有问题,可以用上一个全备恢复。

mysql> select @@expire_logs_days;
+--------------------+
| @@expire_logs_days |
+--------------------+
|                  0 |
+--------------------+
1 row in set, 1 warning (0.00 sec)

配置文件设置过期时间

expire_logs_days=15

2): 手工删除

mysql> purge binary logs to 'mysql-bin.000004';
Query OK, 0 rows affected (0.00 sec)
mysql> purge binary logs before '2020-04-18 22:07:00';
Query OK, 0 rows affected, 1 warning (0.00 sec)

3):全部清空:危险操作(如果主从复制,那么就会宕机)

mysql> reset master;
Query OK, 0 rows affected (0.02 sec)

3.2.3:binlog 的GTID(global transaction id)模式管理

对于一个已提交的事务,并且是一个全局唯一的编号。 所以呢,DML是总个事务的话就只有一个gtid

1):查询GTID有没有开启

mysql>  select @@gtid_mode;
+-------------+
| @@gtid_mode |
+-------------+
| OFF         |
+-------------+
1 row in set (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 |      155 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

2):设置GTID启动

在配置文件加入

gtid-mode=on
enforce-gtid-consistency=true

4): GTID具有幂等性

简单来说就是原来执行过的命令不再执行;我们的sql执行过一次,后边便不再执行;所以我们如果用gtid做恢复的时候默认会跳过这些原有的sql语句,需要加入--skip-gtids 属性来跳过gtid的检查或者在截取mysql-bin的log文件时加入这个参数来过滤

四、slow_log慢日志

慢查询日志一般系统默认是不开启的

1):查询slow_log有没有开启,日志存放位置,时间阀值(大于设定值才被记录单位是秒),不走索引的语句记录

mysql> select @@slow_query_log;
+------------------+
| @@slow_query_log |
+------------------+
|                0 |
+------------------+
1 row in set (0.00 sec)
mysql> select @@slow_query_log_file;
+--------------------------------------+
| @@slow_query_log_file                |
+--------------------------------------+
| /var/lib/mysql/6fcbb41f6f2a-slow.log |
+--------------------------------------+
1 row in set (0.00 sec)
mysql> select @@long_query_time;
+-------------------+
| @@long_query_time |
+-------------------+
|         10.000000 |
+-------------------+
1 row in set (0.00 sec)
mysql> select @@log_queries_not_using_indexes;
+---------------------------------+
| @@log_queries_not_using_indexes |
+---------------------------------+
|                               0 |
+---------------------------------+
1 row in set (0.00 sec)

2):开启慢日志 配置文件

slow_query_log=1
slow_query_log_file=/data/mysql/mysql-slow.log
long_query_time=0.1
log_queries_not_using_indexes=1

3): 解析慢查询日志

过滤相同的慢日志语句和排列出比较重要的语句

-s: 排列顺序 c(次数)

-t: top 靠前条数

mysqldumpslow -s c -t 10 /data/mysql/mysql-slow.log

4):可视化工具解析

pt-query-digest + amemometer