MySQL三种重要日志

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL三种重要日志相关的知识,希望对你有一定的参考价值。

参考技术A

日志是mysql的重要组成部分,其中对于开发而言不得不关注三种重要的日志,分别是二进制日志(bin log)、事务日志(redo log、undo log)。接下来详细介绍这三种日志。

binlog叫做二进制日志,主要是用于记录MySQL表的逻辑变化过程。在实际应用过程中,通常被用于主从复制和数据恢复。

事务执行过程中,会先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

事务提交后的写入只是写入到文件系统的page cache,并没有把数据持久化到磁盘。持久化磁盘由操作系统决定调用fsync。

MySQL提供了配置决定fsync的时机,当sync_binlog=0的时候,每次提交事务只写入page cache,不执行fsync。当sync_binlog=1的时候,表示每次提交事务都会执行fsync。当sync_binlog = N的时候,每次提交事务都写入page cache,累计多个事务才进行fsync。

显然,当sync_binlog = 1的时候,binlog日志不会丢失。当sync_binlog = N的时候,如果发生异常重启,会丢失N个事务的binlog日志。

STATEMENT
记录数据操作的原始SQL,可能引发主库备库因索引选择不一致,导致数据执行结果不一致。

ROW
ROW基于行复制,只记录哪条数据被修改.缺点:占空间。比如DELETE 语句,对于STATEMENT只占用1条SQL。而ROW格式则需要把所有记录的数据记录下来。

MIXED
对于可能引发主备不一致的命令使用ROW格式,否则使用STATEMTNT

对于每一次更新操作,MySQL都需要写入磁盘,然后需要找到对应那条记录并更新。IO成本较高和查找成本都很高。为了提高性能,MySQL会将更新操作写入redo log,并更新内存。INNODB引擎会在适当的时候将操作记录更新到磁盘。

[图片上传失败...(image-c6a1f2-1627716309698)]

undo log主要是记录了数据的逻辑变化,比如对应一条insear语句,undo log会记录一条delete语方便回退到更新前的值。

时刻A发生故障的话,由于binlog未写入,redo log回滚数据,两个日志数据是一致的。

时刻B发生故障,则需要判断binlog是否完整来决定如何恢复。

redo log和bin log的区别?

为什么redo log crash-safe,而bin log不可以?

Mysql日志系统

Mysql的日志系统是保证数据库数据一致性的重要手段,通常包括了binlog,redolog,undolog三种,binlog属于Server层的,也就与底层存储引擎无关,而后两种则属于Innodb存储引擎,目前innodb还是主流存储引擎,因此把这三种统称为日志系统

既然不同架构上工作不同的日志,那么我们先介绍下MySQL的架构吧。

最常用的存储引擎是innodb,这是mysql默认使用的存储引擎,其余的存储引擎有MyIsAm,memory等

binlog

binlong是Server层产生的逻辑日志,binlog又叫归档日志,完整记录数据的每次操作,主要使用在主从备份上,备库会根据binlog来进行数据复制,保证主从一致

Redolog

redolog是innodb特有的物理日志,redolog又叫重置日志,它记录的是数据页的变化,也可以理解为某块的数据发生了变化,它的作用是保证持久化的

redolog的出现是因为在修改数据的时候是将数据读取放到内存中,然后再进行修改最后写入磁盘中,而这个过程中写内存和写硬盘速度天差地别,如果说的更准确地话,那么就是写硬盘其实是随机I/O,非常耗时,所以redolog采用了WAL技术,也就是Write-Ahead-Logging,更直接地说就是日志优先于数据,只要写入了redolog中,甭管有没有修改磁盘中的数据,都认为已经做过修改了,至于什么时候写入磁盘或者准确叫刷盘下面再讲,我们先看看redolog的结构。

redolog有点像hadoop shuffle阶段中的环形缓冲区,可以类比学习,4个logfile默认是1GB,与环形缓冲区一样是循环写入的。正因为是循环写入,所以一定要在覆盖前写入磁盘中,binlog刷盘有三种策略,可以通过innodb_flush_log_at_trx_commit参数来设置,这里说明一下,虽然写redolog是很复杂的事情,不仅要写入Innodb的redo log buffer(就是上面那个图),还要写入整个系统的page cache,这点是因为往往不是整个系统宕机,而是Mysql进程挂了,那么硬要写入磁盘也是件耗成本的事情,最后才是写入磁盘中。

  1. 如果参数为1(也是默认值),那么事务在commit后要主动写入磁盘中
  2. 如果参数为2,那么事务在commit后仅仅写入page cache中而不写入磁盘中,不过如果倒霉,整个服务器死机或者重启就GG了
  3. 如果参数设置为0,事务在commit时没有动作,但平时每秒都会异步看看需不需要刷盘,如果需要就被动刷盘(后台线程是主动的)(这个操作是MySql自己保护自己的,与用户无关,因此这个是效率最高的(我是这么理解的,如若不对请大佬指正))

Undo log

undolog是innodb产生的逻辑日志,用于事务回滚和展示历史记录的,对于数据的任何一次更新都要写undo log,它也不陌生,位于表空间的undo segment中,它的作用是保证隔离性和原子性的(它主要是MVCC机制中的重要手段,可参考我的另一篇博客MVCC - 不要给我歪! - 博客园 (cnblogs.com)

三个日志如何配合呢(换句话就是innodb如何更新数据,也就是update的过程)

简单来说,如果遇到了Update语句,那么首先是服务层发起查询数据请求,存储层从数据页读取到内存,找到该行记录,服务层申请修改数据,存储层先写undolog,之后在更新内存中的数据,并写redolog,直到事务进行commit,服务层自己写binlog,写完之后innodb页进行提交确认。

Question 1:为啥有了binlog了,还要有redo log

一开始Mysql采用的MyisAM存储引擎就没有redolog,只有binlog,这种存储引擎最大的问题就是如果数据库发生异常后重启数据就会丢失,像前面所说的,binlog的功能是给备份数据库进行主从一致的,它记录的是逻辑变化,可以理解为小明花掉100元,如果重启之后只有binlog,那么是小明支付宝少了100元,还是微信少了100元,还是别的地方少了100元,这里的地方就是数据存储的数据页,这种具体说明数据变化就是物理变化,redolog就是干这种事情的,因此redolog具备crash-safe的能力。

Question 2: 为啥redolog要在binlog之前写

相比于binlog,redolog更为关键,如果redolog上没有记录上操作,即便是发生了,我们也不认可,那是因为如果发生了意外,redolog没有记上这笔操作,那么重启后会看redolog的记录,如果没有事务就要进行回滚(仔细想想,redolog真要安全躺在磁盘中事务都要commit,没有commit的事务都可以回滚回去),而且binlog是给备份数据库看的,如果binlog先写,redolog丢失了,主数据库都没这数据,备数据库如果有就很奇怪了。

参考资料

  1. Mysql45讲MySQL实战45讲 (gitee.io)

  2. 文章十二、redo log、bin log、undo log、MVCC - 掘金 (juejin.cn)

  3. 文章详解MySQL事务日志——redo log - 掘金 (juejin.cn)

以上是关于MySQL三种重要日志的主要内容,如果未能解决你的问题,请参考以下文章

MySQL中的日志“binlog”的三种格式

MySQL的三种日志文件

Mysql日志系统

MySQL 的 binlog 的三种格式这么好玩

mysql内存和IO优化一些重要参数

MySQL 5.7 用户与日志管理