vlambda博客
学习文章列表

MySQL的两个日志系统

MySQL中有两个重要的日志模块,分别是redo log(重做日志)和binlog(归档日志)。当我们学习MySQL的时候,这两部分内容是绕不开的,本文我将来详细的介绍一下这两个日志模块,它们在设计上有很多好玩的地方,一些思想也可以在我们工作中使用。

redo log

这里我们举个例子,比如饭店掌柜有个小黑板,专门用来记录客人的赊账记录,如果赊账的人不多,那么他就可以把顾客名字和账目写在小黑板上,如果赊账的人很多,小黑板总会记不下的时候,这个时候掌柜的就需要一个专门记录赊账的账本。

如果有人又要赊账的时候,掌柜就有两种做法:

  • 一种是直接翻开账本找到这个顾客的记录,把这次赊的帐加上去或者划掉。

  • 另一种就是先在黑板上记录,等打烊或者不忙的时候再把账本翻出来记录在账本上。

在生意红火,柜台很忙的时候,掌柜肯定选择第二种做法,因为第一种做法太麻烦了,每次都要翻阅账本找到这个人的记录,账本有很多页,找起来非常浪费时间,找到之后又要核算,整个过程想想都麻烦,相比之下,先在黑板上记录就方便很多。

举上边这个例子是因为MySQL也有这个问题,如果每次更新操作都需要写进磁盘,然后磁盘也要先找到对应的那条数据,然后更新,整个过程IO成本、查找成本很高,为了解决这个问题,MySQL在设计的时候就用了类似饭店记账的思路来提高更新效率。

其实就是MySQL里常说的WAL技术,WAL的全称是Write-Ahead Logging,它的关键点就是先写日志,再写磁盘,也就是先写小黑板,等不忙的时候再写账本。

需要注意的是,先写日志的写日志,其实也是写磁盘,只是写日志是顺序磁盘,速度非常快。

具体的情况就是,当有一条记录需要更新的时候,InnoDB引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就算完成了,InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往在系统比较空闲的时候做,就像打烊了以后写账本一样。

同时,将赊账记录在小黑板上,如果赊账的不多,可以等打烊了以后再记录账本,如果赊账的特别多,小黑板写满了,这个时候掌柜就要放下手上的活,先把黑板上的部分赊账记录更新到账本上,然后将记录好的信息从小黑板上擦掉,为记录新的赊账腾出地方。

MySQL于这个也是类似的,InnoDB的redo log是固定大小的,比如我们可以分配一组4个文件,每个文件的大小都是1GB,那么总共就可以记录4GB的操作,从头开始写,写到末尾就又从开头循环写,write pos是当前记录的位置,一边写一边后移,写到3号文件末尾后就回到0号文件开头,checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据库中。

write pos和checkpoint之间的是“小黑板”上还空着的部分,可以用来记录更新的操作,如果write pos追上了checkpoint,表示“黑板“写满了,这个时候不能再执行新的更新,得停下先擦掉一些记录,把check point推进一下。

redo log是InnoDB引擎所特有的,所以我们在使用InnoDB引擎创建表时,如果数据库发生异常重启,之前提交的记录都不会丢失,InnoDB就是因为有了redo log才有了crash-safe的能力。

crash-safe简单来讲,就好比饭店掌柜的把赊账记录在小黑板上或者账本上,之后饭店突然停业了几天,重新开业后,依然可以通过小黑板和账本上的数据核算赊账账目,

binlog

上一篇文中,我们在说MySQL整体来看,分为两部分,一部是Server层,主要做的是MySQL功能层面的事情,还有一部分是引擎层,负责存储相关的具体事情。上边说的redo log是InnoDB引擎特有的日志,而Server层的日志称为binlog。

这个地方为什么要有两份日志,还要从最开始的时候MySQL中没有InnoDB引擎说起,当时MySQL自带的引擎是MyISAM,但是M有ISAM没有crash-safe的能力,binlog日志只能用来归档,而InnoDB是第三方公司以插件的形式引入MySQL的,因为只依靠binlog是没有crash-safe的能力,所以要使用InnoDB的日志系统redo log。

两种日志主要的不同:

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用

  2. redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”

  3. redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

    往期回顾