数据库
首页 > 数据库> > mysql工具类日志(binlog、slowlog、errorlog)

mysql工具类日志(binlog、slowlog、errorlog)

作者:互联网

mysql日志管理

参考https://www.jianshu.com/p/00c54d2832ed

日志设置

工具日志,不同于undo log(事务等)

错误日志(排错、主从错误)--log-error,默认打开,路径datadir/主机名.err,文本格式,重点关注[ERROR]

慢查询日志(优化)--slow_query_log、--long_query_time

二进制日志(主从)--log-bin、--expire-logs-days

目录授权chown -R mysql.mysql /tmp/{errlog,binlog}

一般会定制这些日志的路径,避免数据盘出错,日志也拿不到

查看错误日志路径:select @@log_error,默认应该在./主机名.err,我的在stderr

修改到mysql.mysql有权限的路径,在/etc/my.cnf的[mysqld]下添加log_error=自定义错误日志路径,如/tmp/errlog/mysql.err或mysql.log(自动创建文件),重启生效

二进制日志(binlog),sql层逻辑日志,记录sql语句操作,默认关闭

开启,需要配置参数(/etc/my.cnf的[mysqld]),重启生效:

innodb_flush_log_at_trx_commit=0:每秒一次将Log Buffer中数据写入到Log File中,并且Flush到磁盘。事务提交不会主动触发写磁盘操作。
innodb_flush_log_at_trx_commit=1:每次事务提交时将Log Buffer数据写入到Log File中,并且Flush到磁盘。
innodb_flush_log_at_trx_commit=2:每次事务提交时将Log Buffer数据写入到Log File中,但不立即Flush到磁盘,MySQL会每秒一次刷新到磁盘。
由于进程调度问题,每条一次操作不能保证每一秒都执行一次。

当innodb_flush_log_at_trx_commit=0时,最近一秒的事务日志存在MySQL的Log Buffer中,无论时MySQL实例停止还是MySQL服务器宕机,都会导致最近一秒的事务日志丢失。
当innodb_flush_log_at_trx_commit=1时,最近一秒的事务日志存在操作系统的文件缓存中,MySQL实例停止不会导致事务日志丢失,但MySQL服务器宕机会导致最近一秒事务日志丢失。

上述的一秒一次刷新,取决于参数innodb_flush_log_at_timeout默认值为1,DDL或其他InnoDB内部操作并不受参数innodb_flush_log_at_trx_commit的限制。

二进制日志概述

二进制日志记录:变更类操作日志,DML增删改(数据)、DDL(增删改表)、DCL(修改权限)

DDL和DCL(如建表create database 库名、alter、drop等),以语句的方式原样记录

DML语句(增删改),记录已提交的事务的SQL语句(未提交或回滚的事务不记录),多种记录格式(statement、row、mixed),通过binlog_format=row参数控制(该参数只控制DML语句),建议使用row。

面试:SBR和RBR的区别,选择依据,看上面的笔记即可。

二进制日志的记录单元:

最小单元event,事件,了解了这些,方便有需要截取某些部分日志做数据恢复的需求,比如如删除某几条数据的恢复这种操作,需要知道截取哪些范围的event

不同类型的语句,事件不同

DDL、DCL以SQL形式记录,每个语句(操作)就是一个事件

DML(标准事务语句begin; 语句1;语句2;commit;,这里有4条语句,4个事件),一个事务包含多个语句,每条语句是一个事件

event事件的开始、结束号码(方便从日志中截取想要的event日志事件范围):

操作二进制文件

查找二进制日志是否开启及位置:从配置文件看,或执行show variables like '%log_bin%';

查看二进制日志文件列表:去log_bin的路径下看,或执行show binary logs;

执行flush logs;会滚动出一个新的日志,再执行show binary logs;就会新增加一个文件。

查看正在使用的二进制文件:show master status;

先做些操作记录事件:

create database binlog charset utf8mb4;

use binlog;

create table t1(id int);

insert into t1 values(1);

查看二进制日志的事件:

show master status;  查看使用的二进制日志文件
show binlog events in '文件名' [limit 10];  查看事件
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.26-log, Binlog ver: 4  |
| mysql-bin.000001 | 123 | Previous_gtids |         6 |         154 |                                        |
| mysql-bin.000001 | 154 | Anonymous_Gtid |         6 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000001 | 219 | Query          |         6 |         335 | create database binlog charset utf8mb4 |
| mysql-bin.000001 | 335 | Anonymous_Gtid |         6 |         400 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000001 | 400 | Query          |         6 |         501 | use `binlog`; create table t1(id int)  |
| mysql-bin.000001 | 501 | Anonymous_Gtid |         6 |         566 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'   |
| mysql-bin.000001 | 566 | Query          |         6 |         640 | BEGIN                                  |
| mysql-bin.000001 | 640 | Table_map      |         6 |         687 | table_id: 108 (binlog.t1)              |
| mysql-bin.000001 | 687 | Write_rows     |         6 |         727 | table_id: 108 flags: STMT_END_F        |
| mysql-bin.000001 | 727 | Xid            |         6 |         758 | COMMIT /* xid=16 */                    |
+------------------+-----+----------------+-----------+-------------+----------------------------------------+
11 rows in set (0.00 sec)

其中前两行是二进制文件头格式,不用关心,第三行事件POS是154

每行一个事件,pos和end_log_pos是事件开始和结束的位置号码,上一个事件的结束位置是下一个事件的开始位置,开始和结束位置可以作为截取事件的依据,事务截取要从begin到commit才完整。

查看二进制日志文件(二进制格式,用工具查看),Linux下查看日志文件类型:file mysql-bin.000001(mysql复制日志)

[root@VM_0_4_centos ~]# file /tmp/binlog/mysql-bin.000001
/tmp/binlog/mysql-bin.000001: MySQL replication log

查看二进制日志内容:mysqlbinlog mysql-bin.000001;或mysqlbinlog mysql-bin.00001 | grep -v '^SET';不看SET开头的事件

@号码,这是一个事件开始的标志,从#@154开始看,那些SET的事件可以跳过不看,可以对照上面的事件查看结果来看,事件的第一行是注释,注明了事件发生时间

其中行模式记录的sql是base64编码的,要想以解码的方式看,-vvv是使结果更加详细,执行:

mysqlbinlog --base64-output=decode-rows -vvv mysql-bin.000001; 执行mysqlbinlog --help可以查看这些参数

# at 687
#200130 21:37:52 server id 6  end_log_pos 727 CRC32 0x209b53a6  Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `binlog`.`t1`
### SET
###   @1=1 /* INT meta=0 nullable=1 is_null=0 */

向binlog.t1插入数据,给第一列设置为1,多列分别为@1,@2...

截取二进制日志:

show binlog events in 'mysql-bin.000001';
mysqlbinlog --start-position=起始位置 --stop-position=结束位置 mysql-bin.000001 [ >/tmp/t1.sql];

查看并截取,其中前两行事件的记录依然存在,使用>可以将截取内容输出到sql文件,可以用于数据恢复。

position是事件在二进制文件中的字节占用的位置。

使用二进制日志进行数据恢复(source sql文件;)

误操作或故障以后做数据恢复

drop 库名 表名;删了表和库。

截取二进制日志从库创建到误删除之前的日志,保持为sql文件。

使用source导入sql文件,这部分不需要记录binlog,因为这些日志是从binlog截取的,再记录binlog,以后用binlog做全量恢复会出问题。使用set sql_log_bin=0;在当前会话中临时设置参数将binlog关闭,不影响其它会话,source命令执行完成以后,执行set sql_log_bin=1;修改回来

二进制日志恢复在数据恢复中必不可少,但是有弊端,如数据量大,时间长,只能作为辅助(使用备份+日志)。

若带过滤截取,只能截取某个库的(因为有use可以标识),不能截取某个表的(没有标识,截取较麻烦,如二次开发改写二进制记录的方式,对表的create和增删改操作加上标识):

mysqlbinlog -d 库名 mysql-bin.000001;

gtid模式(全局事务id)

5.6出现的,但不完善,5.7开始企业中建议将二进制日志文件改为gtid模式管理,某些高级功能新特性必须在RBR模式+gtid下才能使用

gtid之前按事件来组织二进制日志的内容,用事件起始、终止position去截取binlog

gtid之后,对binlog中的每个独立事务(不同于innodb的事务)生产一个gtid号码

ddl和dcl,如create database,一条语句就是一个事件event,就是一个事务,就有一个gtid号码

dml,从begin到commit才是一个事务,有一个gtid号码

gtid组成:server-uuid:TID,server-uuid是数据库第一次启动自动生成的,在数据目录下的auto.cnf文件中(若删除该文件,重启会生成新的,但不要删除和修改它),TID是事务号码,从1开始自增长,不是innodb的事务id

gtid具有幂等性:即用开启了gtid的日志去恢复数据时,系统中存在相同的gtid,若存在重复的gtid自动跳过(执行过的不再执行),会影响binlog的恢复和主从复制

gtid的开启和配置,配置/etc/my.cnf:

gtid-mode=on   开启gtid
enforce-gtid-consistency=true   强制gtid一致性

重启systemctl restart mysqld,gtid开启只影响后面的事务

开启gtid之后操作数据库,执行show master status;在Executed_Gtid_Set列会有值,即server-uuid:TID,其中TID,一个事务是1,n给事务是1-n

执行show binlog events in 'mysql-bin.000001'查看事件,每个事务开始之前有SET设置GTID

截取时使用GTID即可,不用position:

mysqlbinlog --skip-gtids --include-gtids='server-uuid:TID范围,如1-3' mysql-bin.000001 >/tmp/gtid.sql

恢复set sql_log_bin=0; source /tmp/gtid.sql; set sql_log_bin=1;

--skip-gtids参数在导出的时候忽略gtid幂等性(生成的备份不记录原有的gtid信息,恢复时生成新的gtid),否则恢复的时候会检查系统以后的binlog里面是否有要恢复的gtid,有就跳过(幂等性),导致结果不正确。

--include-gtids='server-uuid:TID范围,如1-3',‘server-uuid:TID5',需要导出的事务

--exclude-gtids='server-uuid:TID范围,如1-3',’server-uuid:TID5','server-uuid:TID7',忽略导出的事务

慢查询日志

slowlog,慢查询日志,记录运行慢的sql,优化参考工具,默认关闭

开启,配置/etc/my.cnf的[mysqld]

slow_query_log=1 开关
slow_query_log_file=/tmp/slowlog/slow.log 路径及文件名,/tmp/slowlog需要有mysql.mysql权限,文件名随意
log_query_time=0.1 慢查询时间设定,单位秒,执行select @@long_query_time;(或show variables like '%long_query_time%';)查询默认时间是10.000000秒(不合理,百万数据全表扫描才2-3秒)可以精确到微秒
log_queries_not_using_indexes 没走索引的语句也记录

重启systemctl restart mysqld

构造一张大表,desc 表名;找一个key自带没有值的列(无索引),做查询(全表扫描),构造多条慢查询。

slowlog是文本文件,直接查看即可,记录了超过log_query_time的sql执行记录或没有走索引的查询,包括执行的时间点,库、表、语句、查询时间等。按时间点排序。

过滤,将慢查询日志中,相同的查询语句合并(记录平均查询时间),不同的语句按查询次数(次数多是热语句,优先级高)、Query_time降序排列,使用慢查询分析工具:

mysqldumpslow -s c -t 10 /tmp/slowlog/slow.log  -s是排序,c是次数,-s c是按次数排序,-t 10是top 10,自动按查询时间做第二排序维度

拿到需要优化的sql,去做执行计划分析,如分析是否走索引,或是否需要改写sql等

第三方慢查询分析工具(rpm包)

https://www.percona.com/downloads/percona-toolkit/LATEST下载并安装rpm包

安装依赖:

yum install perl-DBD-MYSQL perl-Time-HiRes perl-IO-Socket-SSL perl-Digest-MD5

运行:

pt-query-diagest /tmp/slowlog/slow.log

安装Anemometer可基于pt-query-digest将慢查询以网页形式可视化。

标签:binlog,bin.000001,log,errorlog,slowlog,mysql,日志,gtid
来源: https://www.cnblogs.com/kibana/p/12245056.html