MySQL binlog&redolog&undolog
binlog(归档日志)
Server层日志
binlog是用于记录数据库表结构和表数据变更的二进制日志。
binlog 用于记录数据库执行的写入性操作(insert、update、delete、create、truncte等,不包括查询select、show等操作)信息,以二进制的形式保存在磁盘中。
binlog 是 mysql的逻辑日志,并且由 Server 层进行记录,使用任何存储引擎的 mysql 数据库都会记录 binlog 日志。
biglog会记录下每条变更的sql语句,还有执行开始时间、结束时间、事务id等信息。
binlog 是通过追加的方式进行写入的,可以通过max_binlog_size 参数设置每个 binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。
逻辑日志和物理日志区别:
逻辑日志:可以简单理解为记录的就是sql语句 。
物理日志:mysql 数据最终是保存在数据页中的,物理日志记录的就是数据页变更 。
binlog使用场景:
主从复制:在 Master 端开启 binlog ,然后将 binlog发送到各个 Slave 端, Slave 端重放 binlog 从而达到主从数据一致。主从延迟一般在100ms以内。
数据恢复:通过使用 mysqlbinlog 工具来恢复数据。因为binlog记录了数据库的变更,所以可以用于数据恢复。
binlog刷盘时机:
对于InnoDB存储引擎而言,只有在事务提交时才会记录binlog,此时记录还在内存中,那么binlog是什么时候刷到磁盘中的呢?
mysql通过sync_binlog参数控制binlog的刷盘时机,取值范围是0-N:
0:不去强制要求,由系统自行判断何时写入磁盘
1:每次commit的时候都要将binlog写入磁盘(最安全的设置,MySQL 5.7.7之后版本的默认值)
N:每N个事务,才会将binlog写入磁盘
MySQL使用binlog主从同步的逻辑:
redo log
InnoDB引擎层的日志
MySQL使用页作为存储结构,在更新操作时,MySQL会先把这条记录所在的页加载到内存中,然后对记录进行修改,最后将更新从内存刷到磁盘中。
在更新操作很频繁时,如果每一次的更新操作都需要写磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程IO成本,查找成本都很高。
redo log 包括两部分:一个是内存中的日志缓冲( redo log buffer ),另一个是磁盘上的日志文件( redo logfile)。
mysql 每执行一条 DML 语句,先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。这种 先写日志,再写磁盘 的技术就是 MySQL里经常说到的 WAL(Write-Ahead Logging) 技术。
WAL技术:
WAL的全称是Write-Ahead Logging,即写前日志,它的关键点是先写日志,再写磁盘,以便故障时进行恢复。
具体来说,当有一条语句需要更新的时候,InnoDB引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就算完成了。同时InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。
另外,InnoDB的redo log是固定大小的,从头开始写,写到末尾就又回到开头循环写,因此要在覆盖记录前把记录更新到数据文件中。
因为修改是先更新内存的,如果在还没得及刷新到磁盘,数据库宕机了,就会造成修改数据丢失。有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。
为什么会有redo log和binlog两份日志呢?
因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。
而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力
这两种日志有以下三点不同:
1、redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
2、redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
3、redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
4、redo log 是恢复在内存更新后,还没来得及刷到磁盘的数据。 binlog是存储所有数据变更的情况,理论上只要记录在binlog上的数据,都可以恢复。
undo log
undo log记录的是数据修改之前的数据。主要用于回滚,MySQL数据库事务的原子性就是通过 undo log实现的。
undo log主要存储的是数据的逻辑变化日志,比如我们要 insert 一条数据,那么 undo log 就会生成一条对应的 delete 日志。所以当需要回滚时,只需要利用undo log 就可以恢复都修改前的数据。
undo log另一个作用是用来实现多版本并发控制 MVCC。
undo记录中包含了记录更改前的镜像,如果更改数据的事务未提交,对于隔离级别大于等于 read commit的事务而言,不应该返回更改后的数据,而应该返回更改前的数据。
总结:
binlog是server层用于记录数据库表结构和表数据变更的二进制形式的逻辑日志,主要用于主从同步和数据恢复
redo log是存储引擎层用来记录对数据做了什么修改的物理日志,主要用于恢复在内存更新后,还未来得及刷到磁盘的数据。及保证事务的持久性。
undo log 是存储引擎层用来记录数据修改之前数据的物理日志,主要用于实现回滚和MVCC多版本并发控制。及保证事务的原子性。
提交事务时,redolog、undolog、binlog的生成时机:
执行 SQL 语句时,MySQL 将操作的数据页读入 buffer pool,然后对其进行修改,并将修改后的数据记录到 redo log buffer 和 bin log 中。
对于更新操作,MySQL 会先将旧的数据页复制一份并存储到 undo log 中,再将新的数据页存储到 buffer pool 中。
在事务提交时,MySQL 会将 redo log buffer 中的内容写入磁盘的 redo log 文件中,并将事务持久化到磁盘中。如果事务异常结束,可以通过 redo log 进行恢复。
bin log 是 MySQL 的二进制日志文件,用于记录所有 DDL 和 DML 操作,包括更新和删除数据等,便于在主从复制、数据恢复和点-in-time 恢复等场景下使用
附录:
mysqlbinlog 工具分析binlog日志
1、查看是否开启binlog,ON开启,OFF没有开启,命令:show variables like '%log_bin%';
2、查看binlog文件
查看当前写入的binlog文件名:
SHOW MASTER STATUS;
3、查找mysqlbinlog的位置
(1)默认位置,使用命令:which mysqlbinlog
(2)自定义位置,我的在 mysql安装目录的log文件夹中
4、使用命令分析日志
mysqlbinlog --no-defaults --database=数据库名 --base64-output=decode-rows -v --start-datetime='2020-07-14 09:56:00' --stop-datetime='2020-07-14 09:58:00' mysql-bin.000052| more
将binlog转成sql语句:
binlog2sql:https://github.com/danfengcao/binlog2sql
参考:https://hiddenpps.blog.csdn.net/article/details/108505371
END.