MySQL为什么需要binlog、redo log和undo log

296 阅读3分钟

mysql.gif

Buffer Pool

Buffer Pool就是一块用于缓存MySQL磁盘数据的内存空间。

Buffer Pool避免每个SQL操作直接io操作,通过批量操作从而提高效率。

redo log

redo log解决MySQL服务器宕机导致Buffer Pool数据丢失的问题。如果出现宕机后启动可以根据redo log重新恢复。

过程如下:

redolog.gif

redo log是磁盘顺序写,数据刷盘是磁盘随机写。

预写式日志:先预写日志后面再将数据刷盘的机制。

redo log buffer

redo log的刷盘机制由参数innodb_flush_log_at_trx_commit控制。 落盘/刷盘机制:

  1. innodb_flush_log_at_trx_commit = 1:实时写(os cache),实时刷(os cache -> 磁盘)。【这种策略会在每次事务提交之前,每次都会将数据从redo log刷到磁盘中去,理论上只要磁盘不出问题,数据就不会丢失。】
  2. innodb_flush_log_at_trx_commit = 0:延迟写,延迟刷。【这种策略在事务提交时,只会把数据写到redo log buffer中,然后让后台线程定时去将redo log buffer里面的数据刷到磁盘。这种策略是最高效的,但是我们都知道,定时任务是有间隙的,但是如果事务提交后,后台线程没来得及将redo log刷到磁盘,这个时候不管是MySQL进程挂了还是操作系统挂了,这一部分数据都会丢失。】
  3. innodb_flush_log_at_trx_commit = 2:实时写,延迟刷。【这种策略在事务提交之前会把redo log写到os cache中,但并不会实时地将redo log刷到磁盘,而是会每秒执行一次刷新磁盘操作。这种情况下如果MySQL进程挂了,操作系统没挂的话,操作系统还是会将os cache刷到磁盘,数据不会丢失,如下图:】

1.gif

所以,这种redo log刷盘策略是上面两种策略的折中策略,效率比较高,丢失数据的风险比较低,绝大多情况下都推荐这种策略。

回滚 - undo log

InnoDB是支持事务的,而事务是可以回滚的。

假如一个事务将age=1修改成了age=2,在事务还没有提交的时候,后台线程已经将age=2刷入了磁盘。这个时候,不管是内存还是磁盘上,age都变成了2,如果事务要回滚,找不到修改之前的age=1,无法回滚了。

undo.gif

回滚.gif

binlog

记录过程是先写Binlog Buffer,然后通过刷盘时机,控制刷入OS Buffer,控制fsync()进行写入Binlog File日记磁盘的过程。

binlog以追加方式记录修改之后的数据,用于归档。 和redo log日志类似,binlog也有着自己的刷盘策略,通过sync_binlog参数控制:

  • sync_binlog = 0 :每次提交事务前将binlog写入os cache,由操作系统控制什么时候刷到磁盘。
  • sync_binlog =1 :采用同步写磁盘的方式来写binlog,不使用os cache来写binlog。
  • sync_binlog = N :当每进行n次事务提交之后,调用一次fsync将os cache中的binlog强制刷到磁盘。

刷盘时机

对于Binlog,MySQL是通过参数sync_binlog参数来控制刷盘时机,取值是0、1和N三种值。简单理解为刷盘时机控制的是数据从 buffer区 -> os cache -> 磁盘。

刷盘时机.jpeg

Binlog 记录格式

Binlog.png

作用

  • 主从复制场景:在Master主端开启Binlog,将Binlog发生到各个Slave从端,Slave从端重放Binlog从而达到主从数据一致。
  • 数据恢复场景:通过使用 mysqlbinlog 工具来恢复数据。

binlog & redo log 区别

  • binlog是逻辑日志,记录的是对哪一个表的哪一行做了什么修改;redo log是物理日志,记录的是对哪个数据页中的哪个记录做了什么修改,如果你还不了解数据页,你可以理解成对磁盘上的哪个数据做了修改。
  • binlog是追加写;redo log是循环写,日志文件有固定大小,会覆盖之前的数据。
  • binlog是Server层的日志;redo log是InnoDB的日志。如果不使用InnoDB引擎,是没有redo log的。

最终图示为:

image.png

文章来自