详解mysql的redo log

85 阅读3分钟

一.为什么会有redo log

如果每次修改一条数据,就把整个内存页数据刷新到磁盘是非常浪费的,并且由于一个事务可能包含了多个执行语句,而执行语句对应的数据可能分散在不同的数据页,这样写磁盘就是多次随机IO操作,性能是非常低下的。

所以InnoDB引擎就引入了Redo Log来提高性能,Buffer Pool中的数据修改,并不需要立即就刷新到磁盘中。

每一条数据的修改,都会生成一条redo log记录,redo log也有自己的缓冲区存放数据修改记录。当每个事物提交,就会把缓冲区的记录刷到磁盘,同时由于磁盘中redo log的写入是顺序IO,所以效率也很高。变相来说,redo log实现了内存页数据刷新到磁盘从随机IO变成了顺序IO,当然Buffer Pool本身在刷新数据到磁盘中可能还是随机IO。

与在事务提交时将所有修改过的内存中的页面刷新到磁盘中相比,只将该事务执行过程中产生的redo日志刷新到磁盘的好处如下:

1.1redo日志占用的空间非常小

存储表空间ID、页号、偏移量以及需要更新的值所需的存储空间是很小的。

1.2redo日志是顺序写入磁盘的

在执行事务的过程中,每执行一条语句,就可能产生若干条redo日志,这些日志是按照产生的顺序写入磁盘的,也就是使用顺序IO。

二.redo 日志写入过程

2.2.1 redo log block和log buffer 前面提到了,redo log本身也有自己对应的缓冲区,实际上在服务器启动时就向操作系统申请了一大片称之为redo log buffer的连续内存空间,简称为log buffer。

这片内存空间被划分成若干个连续的redo log block,InnoDB把redo日志都放在了大小为512字节的块(block)中(对应磁盘块),可以通过启动参数innodb_log_buffer_size来指定log buffer的大小,该启动参数的默认值为16MB。

向log buffer中写入redo日志的过程是顺序的,也就是先往前边的block中写,当该block的空闲空间用完之后再往下一个block中写。

2.2.2 redo log刷盘时机 log buffer的记录需要按照一定的策略被刷新到redo log的磁盘文件中,比如:

log buffer空间不足

log buffer的大小是有限的(通过系统变量innodb_log_buffer_size指定),如果不停的往这个有限大小的log buffer里塞入日志,很快它就会被填满。

InnoDB认为如果当前写入log buffer的redo日志量已经占满了log buffer总容量的大约一半左右,就需要把这些日志刷新到磁盘上。

事务提交时

前边说过之所以使用redo日志主要是因为它占用的空间少,还是顺序写,在事务提交时可以不把修改过的Buffer Pool缓存页刷新到磁盘,但是为了保证持久性,必须要把修改这些页面对应的redo日志刷新到磁盘。

后台有一个线程,大约每秒都会刷新一次log buffer中的redo日志到磁盘。 正常关闭服务器时等等。