Mysql—二进制日志(binlog)

什么是二进制日志(binlog)

binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、DELETE、UPDATE…)的二进制日志。多说一句,如果update操作没有造成数据变化,也是会记入binlog。

binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但你可以通过查询通用日志来查看MySQL执行过的所有语句。

逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。但又不完全是sql语句这么简单,而是包括了执行的sql语句(增删改)反向的信息,也就意味着delete对应着delete本身和其反向的insert;update对应着update执行前后的版本的信息;insert对应着delete和insert本身的信息。

在使用mysqlbinlog解析binlog之后,一切都会真相大白。因此可以基于binlog做到类似于oracle的闪回功能,其实都是依赖于binlog中的日志记录。

二进制日志包括两类文件:

  • 索引文件(文件名后缀为.index)用于记录所有的二进制文件,即哪些日志文件正在被使用。如:mysql-bin.index。
  • 日志文件(文件名后缀为.00000*)用于记录数据库所有的DDL和DML(除了数据查询语句)语句事件。如:mysql-bin.000001

二进制日志在my.cnf中的相关配置:

log_bin: on                                        # 打开binlog日志
log_bin_index: /var/log/mysql/mysql-bin.index      # bin文件index,即索引文件名称
log_bin_basename: /var/log/mysql/mysql-bin         # bin文件路径及名前缀,即日志文件名称前缀

二进制日志作用场景

主要用在两个场景:主从复制和数据恢复

1、主从复制场景:在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。在 Master 主端开启Binlog,将Binlog发送到各个 Slave 从端,Slave 从端重放 Binlog 从而达到主从数据一致。

2、数据恢复场景:用于数据库的基于时间点的还原。通过使用 mysqlbinlog 工具来恢复数据。

3、日志审计场景:用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入攻击。

二进制日志文件详解

1、日志记录过程

日志文件,在innodb里其实又可以分为两部分,一部分在缓存中,一部分在磁盘上。Binlog 大致记录过程是先写 Binlog Buffer,然后通过刷盘时机,控制刷入 OS Buffer,控制 fsync() 进行写入 Binlog File 文件到磁盘的过程。这里业内有一个词叫做刷盘,就是指将缓存中的日志刷到磁盘上。刷盘时机,是指啥时候,通过什么策略将内存日志写入到磁盘中。因为日志每次都是先写入内存buffer中,然后通过刷盘时机设置的参数控制刷盘时机,然后才刷入到磁盘上。跟刷盘有关的参数有两个:sync_binlog和binlog_cache_size。

2、刷盘时机参数

sync_binlog=[N]: 表示写缓冲多少次,刷一次盘。默认值为0。取值是 0、1 和 N 三种值。

binlog_cache_size: 二进制日志缓存部分的大小,默认值32k。设置过大,会造成内存浪费。设置过小,会频繁将缓冲日志写入临时文件。

sync_binlog=0: 表示刷新binlog时间点由操作系统自身来决定,操作系统自身会每隔一段时间就会刷新缓存数据到磁盘,这个性能最好。

sync_binlog=1: 表示每次事务提交都要调用fsync(),刷新binlog写入到磁盘。

sync_binlog=N: 表示 N个事务提交,才会调用 fsync()进行一次binlog刷新,写入磁盘。

3、什么时候产生

事务提交的时候,一次性将事务中的sql语句(一个事物可能对应多个sql语句)按照一定的格式记录到binlog中。

这里与redo log很明显的差异就是redo log并不一定是在事务提交的时候刷新到磁盘,redo log是在事务开始之后就开始逐步写入磁盘。

因此对于事务的提交,即便是较大的事务,提交(commit)都是很快的,但是在开启了bin_log的情况下,对于较大事务的提交,可能会变得比较慢一些。这是因为binlog是在事务提交的时候一次性写入的造成的,这些可以通过测试验证。

4、什么时候释放

binlog的默认是保持时间由参数expire_logs_days配置,也就是说对于非活动的日志文件,在生成时间超过expire_logs_days配置的天数之后,会被自动删除。

5、对应的物理文件

日志文件的路径为log_bin_basename,binlog日志文件按照指定大小,当日志文件达到指定的最大的大小之后,进行滚动更新,生成新的日志文件。对于每个binlog日志文件,通过一个统一的index文件来组织。

6、日志记录格式

MySQL 5.7.7 版本之前默认格式是 STATEMENT,版本之后默认是 ROW,可以通过参数 binlog-format 指定。

常见查询命令

1、查询二进制日志文件的保存路径

mysql> show variables like '%log_bin%';
mysql> show variables like '%log_bin_basename%';

2、查询二进制日志文件的保存时间

mysql> show variables like '%expire_logs_days%';

3、查看binlog日志

mysql> show binary logs;      # 查看所有binlog文件文件列表
mysql> show master logs;      # 查看所有binlog日志文件列表
mysql> show master status;    # 查看当前正在写入的binlog文件,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Position)值

mysql> show binlog events;                            # 查看第一个binlog文件的内容
mysql> show binlog events in 'mysql-bin.000002';      # 查看指定的binlog文件的内容

[root@localhost ~]# mysqlbinlog mysql-bin.000001          # 使用mysqlbinlog命令查看日志文件内容,一般的statement格式的二进制文件。
[root@localhost ~]# mysqlbinlog -vv mysql-bin.000001      # 使用mysqlbinlog命令查看日志文件内容,如果是row格式,加上-v或者-vv参数就行。

4、删除binlog日志

mysql> reset master      # 将会删除所有日志,并让日志文件重新从000001开始。

mysql> PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
mysql> purge binary logs to "mysql-bin.000002";   # 将会清空000002之前的所有日志文件,将binary换成master也可以。

# 使用--expire_logs_days=N选项指定过了多少天日志自动过期清空。

5、flush刷新log日志,自此刻开始产生一个新编号的binlog日志文件

mysql> flush logs;

应用场景二:数据恢复

https://www.sohu.com/a/275633000_684445

https://www.cnblogs.com/zonglonglong/p/12275934.html

原文地址:https://www.cnblogs.com/liuhaidon/p/11493292.html