错误日志

作用:记录MYSQL从启动以来,所有的状态、警告、错误,可以帮助管理员定位数据库问题。

错误日志默认为开启状态,文件默认位于/datadir/hostname.err,如我的电脑的错误日志:

16292748951.png

binlog二进制日志

作用:记录数据库变化(DDL、DML、DCL都记录,除select外)的日志,在数据恢复、主从复制中应用。

binlog日志在8.0版本以前默认没有开启,建议在生产环境都进行开启。

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

记录SQL语句种类:

  • DDL:原封不动的记录当前的DDL
  • DCL:原封不动的记录当前DCL
  • DML:只记录已经提交的事务DML(insert, update, delete)

DML三种记录方式(受binlog_format参数影响,可以设置binlog的记录方式):

  • statement,5.6的默认格式,SBR(statement based replication),语句模式原封不动地记录当前DML
  • row,5.7的默认格式,RBR(row based replication),记录数据行的变化(用户未必看得懂,需要工具分析)
  • mixed,混合模式,MBR(mixed based replication),以上两种模式混合

SBR与RBR模式的区别:、
SBR可读性高,日志量少,但是不够严谨
RBR可读性低,日志量大,足够严谨
举个例子,update t1 set xxx=xxx where id >= 1,影响了所有数据行,SBR模式只会记录这一个SQL语句,但是RBR模式会记录所有受影响的行的变化。另外,RBR模式的严谨性还体现在函数使用上,比如insert into t1 values(1, 'zs', now()),SBR模式仍然只记录该SQL语句,但是RBR模式记录了当前时间。当进行数据恢复时,SBR模式下now()的值已经发生变化,会导致数据错误。

在生产环境中,推荐使用row(RBR)模式。

event,事件,是binlog日志的最小记录单元,对于DDL, DCL, DML来说,一个语句就是一个事件;另外对DML来说,只记录已经提交的事务。
以下例子就被分成了四个事件:

begin;  120-340(事件的起始位置和结束位置)
DML1;   340-460
DML2;   460-550
commit; 550-760

事件由三部分组成:事件开始的标识、事件内容、事件结束的标识
记录事件的开始和结束位置号的作用:方便用户截取事件

binlog文件的查看

查看是否开启binlog:	mysql>select @@log_bin;
文件位置:		mysql>select @@log_bin_basename;
查看事件:
	mysql>show master status;
	mysql>show binlog events in 'binlog.000093';

事件查看的另外一种方式,直接使用mysqlbinlog命令,把binlog文件按照sql的格式输出到指定文件:

# mysqlbinlog --base64-output=decode-rows -vvv binlog.000093 >/tmp/a.sql
# vim /tmp/a.sql

日志截取恢复:

mysql>flush logs; # 滚动一个新的日志文件

日志截取恢复过程:
1. 分析binlog,找到回滚的起点position和终点position
2. 截取日志 # mysqlbinlog --start-position=219 --stop-position=1357 /data/binlog/binlog.000093 >/tmp/bin.sql
3. 恢复日志 
	mysql>set sql_log_bin=0;
	mysql>source /tmp/bin.sql;
	mysql>set sql_log_bin=1;
4. 验证恢复的正确性

以上恢复比较死板,更灵活的方法:
1. 只截取指定数据库的日志:# mysqlbinlog -d database_name --start-position=219 --stop-position=1357 /data/binlog/binlog.000093 >/tmp/bin.sql
2. 日志分布在多个binlog文件,可以按照时间来截取日志:# mysqlbinlog -d database_name --start-datetime=“2020-03-20 10:00:00” --stop-datetime=“2020-03-21 10:00:00” /data/binlog/binlog.000093 /data/binlog/binlog.000094 >/tmp/bin.sql
3. 按时间只能精确到秒,如果一秒钟发生了多个事件,无法剔除,可以尝试加上 -no-defaults 参数,报错不停止
4. 数据库定时备份+binlog是我们数据恢复时的主要手段,只使用binlog的场景比较少,或者数据库上阿里云,直接用云服务提供的备份(快照)

binlog维护:

手动滚动日志文件:mysql>flush log;
日志删除(不要使用rm命令):
	1. 自动删除:select @@expire_logs_days; 设置为两个全备周期稳妥点
	2. 手动删除:purge binary logs to 'binlog.000093'; binlog.000093前的都删除掉
	3. 全部清空并重置开始序号:reset master;这个行为比较危险

binlog的GTID(global transaction id,全局事务id)模式管理
GTID是对一个已经提交的事务(DDL,DCL一个语句就是一个事务)编号,并且是一个全局唯一的编号,主要为了主从复制而来的
GTID=server_uuid:transaction_id(transaction_id递增的)
基于GTID来截取日志:

# mysqlbinlog -d database_name --include-gtids='dff98809-55c3-11e9-a58b-000c2928f5dd:5-11' --exclude-gtids='dff98809-55c3-11e9-a58b-000c2928f5dd:7-8'  /data/binlog/mysql-bin.000003 /data/binlog/mysql-bin.000004 >/tmp/gtid.sql
以上恢复会失败,因为没加--skip-gtids参数,导致导出的sql携带已经执行过的gtids,执行时由于GTID幂等性直接跳过的。

GTID具备幂等性,mysql恢复binlog时,重复的GTID的事务不会再执行了,直接跳过。所以截取时加上--skip-gtids,可以使得导出的sql没有gtid信息,运行时能正常执行,不会被跳过。
使用GTID来恢复要方便一些。

slowlog慢日志

作用:记录mysql运行中较慢的查询语句。
默认是没有开启慢日志的,开启配置:

mysql>select @@slow_query_log; 是否开启慢日志
mysql>select @@slow_query_log_file; 慢日志文件位置
mysql>select @@long_query_time; 慢语句的时间阈值,建议是按业务来循序渐进地降低
mysql>select @@log_queries_not_using_indexes; 不走索引的语句记录

mysqldumpslow命令工具可以对慢日志进行统计分析,比直接看慢日志要合理高效一些:

# mysqldumpslow -s c -t 10 /data/aaa-slow.log