redo日志,也被称为重作日志,对数据库中表的操做进行记录,能够用于系统崩溃时的数据恢复。web
例如,某个事务将系统表空间中的第100号页面中偏移量为1000处的那个字节的值1改成了2,咱们只须要记录将第0号表空间的100号⻚⾯的偏移量为1000处的值更新为2,这样咱们在事务提交时,把上述内容刷新到磁盘中,即便以后系统崩溃了,重启以后只要按照上述内容记录的步骤从新更新一下数据页,那么该事务对数据库中所作的修改又能够被恢复出来。数据库
与在事务提交时将全部修改过的内存中的页面刷新到磁盘中相比,只将事务执行过程当中产生的redo日志刷新到磁盘的好处以下:服务器
各个部分详细释义以下:svg
一条语句在执行过程当中可能修改若干个页面。这些页面的更改都发生在Buffer Pool中,因此在修改完页面以后,须要记录下相应日志的redo日志。在执行语句的过程当中产生的redo日志在InnoDB中划分红了若干个不可分割的组,好比:spa
什么是不可分割?不可分割相似于事务,即要么都完成,要么都不完成。操作系统
咱们以向某个索引对应的B+树插入一条记录为例,在向B+树中插入这条记录以前,须要先定位到这条记录应该被插入到哪一个叶子节点表明的数据页中,定位到具体的数据页以后,有两种可能的状况:翻译
若是在悲观插入过程当中,新的页面已经分配好了,数据也复制过去了,新的记录也插入到该页面中了,但是没有向内节点中插入一条目录项记录,这个插入就是不完整的,这样会造成一颗不正确的B+树。3d
InnoDB中规定,在执行这些保证原子性的操做时必须以组的形式来记录的redo日志,要么把所有的日志都恢复掉,要么一条都不恢复。如何作到这些的呢?日志
有的须要保证原子性的操做会生成多条redo日志,好比向某个索引对应的B+树中进行一次悲观插入就须要生成许多条redo日志。如何把这些redo日志划分到一个组内的呢?就是在组中的最后一条redo日志后边加上一条特殊类型的redo日志,该类型名称为MLOG_MULTI_REC_END,type字段对应的十进制数字是31,此时至关于加了一个结束标志。这样在系统崩溃重启进行恢复时,只有当解析到类型为MLOG_MULTI_REC_END的redo日志,才认为解析到了一组完整的redo日志,才会进行恢复,不然的话,直接放弃前边解析到的redo日志。
xml
有时候须要保证原子性的操做只生成一条redo日志,好比更新Max Row ID属性的操做就只会生成一条redo日志。其实在一条日志后边跟一个类型为MLOG_MULTI_REC_END的redo日志也是能够的,不过为了节省空间,他们不想浪费⼀个⽐特位。 别忘了虽然redo⽇ 志的类型⽐较多, 但撑死了也就是⼏⼗种, 是⼩于127这个数字的, 也就是说咱们⽤7个⽐特位就⾜以包括全部的redo⽇志类型,⽽type字段实际上是占⽤1个字节的, 也就是说咱们能够省出来⼀个⽐特位⽤来表示该须要保证原⼦性的操做只产⽣单⼀的⼀
条redo⽇志, 示意图以下:
顾名思义,Mini-Transaction就是微事务。把对底层页面中的一次原子访问的过程称之为一个Mini-Transaction,简称为mtr,一个所谓的mtr能够包含一组redo日志,在进行崩溃恢复时这一组redo日志做为一个不可分割的总体。
一个事务能够包含若干条语句,每一条语句实际上是由若干个mtr组成,每个mtr又能够包含若干条redo日志。
InnoDB为了解决磁盘速度过慢的问题而引入了Buffer Pool。同理,写入redo日志时也不能直接写到磁盘上,实际上在服务器启动时就向操做系统申请了一大片称之为redo log buffer的连续内存空间,翻译过来就是redo日志缓冲区,简称log buffer。
向log buffer中写⼊redo⽇ 志的过程是顺序的, 也就是先往前边的block中写, 当该block的空闲空间⽤完以后再往下⼀个block中写。 当咱们想往log buffer中写⼊redo⽇ 志时, 第⼀个遇到的问题就是应该写在哪一个block的哪一个偏移量处, InnoDB提供了⼀个称之为buf_free的全局变量, 该变量指明后续写⼊的redo⽇ 志应该写⼊到log buffer中的哪一个位置。