1.前景

  在Mysql中,就我自己的角度来看到所有的日志文件,那么我认为redo log 和undo log是Mysql日志中必不可少的一节。

2. Redo Log 特点

  这里先要介绍一下WAL机制:当执行提交事务之后,并不是直接修改到数据文件中的,而是先要保证将相关的操作日志记录到Redo文件中,数据库后台会根据自身的机制(这里的内存中的数据页刷新到磁盘上的机制)将内存中的脏数据刷新到磁盘中。之所以这么做其目的主要有以下两点:

  • 写入数据文件时随机I/O比较慢,用户执行提交之后一定要等到数据文件同步写入完成后才返回成功(这里个人理解是如果没有redo log的话,当执行commit 后,会出现短暂性的阻塞),这样用户体验就会很差(内存中的脏页刷盘是随机写的)  
  • 如果提交一个很大的事务要就进行大量的随机I/O同步写入,那么数据库就会有抖动的,
  • 做自动故障恢复(前滚)

随机i/O转换为顺序i/O,对脏数据的刷新在后台可以进行阶段性操作,并且可以做相关的i/O合并,是整体性能得到提升。其中做自动故障恢复主要是通过redo log恢复数据库崩溃前时内存中的状态,保证数据库在崩溃时事务不会丢失。  

  通常,我们往往会在innodb存储引擎的数据目录下看到会有两个名为ib_logfile0和ib_logfile1的文件,这两个文件在Mysql官方文档上将其称为innodb存储引擎的日志文件。该日志主要是用来保证事务的原子性和持久性。

  其中,它保证事务的持久性主要是由两部分组成,一是内存中的重做日志缓冲(redo log buffer),该大小主要是由innodb_log_buffer_size参数控制,而是由重做日志文件(redo log file),主要是由参数innodb_log_file_size控制,

3.Redo Log格式 

  Redo Log日志格式主要分为两种:物理日志和逻辑日志

  其中物理日志就是将变化对象的新旧状态都记录到日志中,而逻辑日志主要记录的就是逻辑语句,类似于Mysql中binlog,优势在于日志量非常少,

思考:为什么Redo log要用物理日志和逻辑日志两种混合形态进行记录吗?

4.checkpoint概念(略谈)

  众所周知,当数据库发生崩溃时,可以利用redo log的前滚机制进行数据实例的恢复,但是如果Redo文件足够大,那么这样的数据库在做实例恢复时所需要的时间就会变得足够长,显然这是不可被容忍的,因此,在数据库引入了checkpoint(检查点)机制

  checkpoint作用

  • 缩短数据库的恢复时间
  • 缓冲池不够用时,将脏页刷新到磁盘
  • 重做日志不可用时,刷新脏页

  checkpoint刷新策略:

  因此,当数据库发生宕机时,数据库不需要重做所有的日志,因为checkpoint之前的数据都已经刷新到磁盘。故数据库只需要对checkpoint后的重做日志进行恢复,这样就大大地减少了恢复时间。  

  此外,当缓冲池不够用时,根据LRU算法会溢出最近最少使用的页,若此页为脏页,那么需要强行执行checkpoint,将脏页也就是页的新版本刷回到磁盘。

  重做日志不可用的情况是,因为当前的重做日志是循环使用的,并不是让其无限增大,重做日志可以被重用的部分是指这些重做日志已经不再需要,即当数据库发生宕机时,数据库恢复操作不需要这部分的重做日志,因此这部分就可以被覆盖重用,若此时重做日志还需要使用,那么就必须强制产生Checkpoint,将缓冲池中的页至少刷新到当前重做日志的位置(这时会就出现极客林晓斌所说数据库抖动的情况,其实这种情况的产生大部分是由于写入的长事务到数据库中)。

  那么checkpoint是如何具体判断刷新?

  对于innodb存储引擎而言,其主要是通过LSN(Log Sequence Number)来标记版本的,可以通过如下命令进行查看:  

---
LOG
---
Log sequence number 996682662      //Redo 日志缓冲区中的LSN
Log flushed up to   996682662      //Redo 日志文件中的LSN
Pages flushed up to 996682662      //写入磁盘中的数据页对应的LSN
Last checkpoint at  996682653      //最后一个checkpoint对应的LSN

  在innodb存储引擎中,Checkpoint发生的时间、条件以及脏页的选择等都非常复杂。而Checkpoint所做的事情无非是将缓冲池中的脏页刷回到磁盘,不同在于每次刷新多少页到磁盘,每次从哪里取脏页。以及什么时间触发checkpoint。在innodb存储引擎中,主要有两种checkpoint:一种是Sharp checkpoint(全量检查点),另一种是Fuzzy checkpoint(模糊检查点).

  sharp checkpoint 发生在数据库关闭时将所有的脏页都刷回磁盘,这时默认的工作方式,由参数innodb_fast_shutdown=1控制

  如果在数据库运行的阶段也采用sharp checkpoint,那么数据库的可用性就会受到很大的影响,故在innodb存储引擎内部使用Fuzzy Checkpoint进行页的刷新,即只是刷新部分页,而不是刷新所有的脏页到磁盘。 

在innodb存储引擎中可能发生如下几种情况的Fuzzy Checkpoint(这个应该会在innodb之存储引擎篇中详解):

  • Master thread Checkpoint
  • Flush_LRU_LIST checkpoint
  • Async/sync Flush Checkpoint
  • Dirty page too much Checkpoint

5.Redo日志和binlog日志协调工作  

  说到这里就要谈谈两阶段提交,当会话发起commit(提交)工作时,先进行存储引擎的prepare(准备)工作,这里的prepare工作只是在对应的Redo日志上打上prepare标记,随后会写入binlog并执行fsync(系统调用,对binlog执行磁盘同步),最后再Redo日志记录上打上commit标记表示记录以提交完成。  

 

6.Redo日志的一些参数说明:

innodb_log_file_size            ##每个redo log日志大小(对应磁盘上的文件就是ib_logfile0/ib_logfile1  ...)
innodb_log_group_home_dir    ##这个是redo log日志的存在磁盘的目录,默认是数据目录下
innodb_log_files_in_group       ##指定日志文件组中重做日志文件的数量,默认是2
innodb_flush_log_at_trx_commit = n  ##双一之一,表示redo log flush 磁盘机制,与后面的sync_binlog会细说
innodb_mirrored_log_groups          ##指定了日志镜像文件组的数量,默认为1