一、前言
日志是记录我们系统运行的点点滴滴,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