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

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

img

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

binlog

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

Redolog

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

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

MySQL--buffer pool、redo log、undo log、binlog_黄智霖-blog的博客-CSDN博客

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)