Mysql 百问系列:redo log 作什么用?

Mysql 百问系列:redo log 作什么用?

问题redo log 由来为何redo log 的信息在崩溃的时候不会丢失?redo log bufferCheckpoint总结系列文章web

问题

  • 为何要设计redo log?
  • 什么又是redo log buffer ?
  • 什么是checkpoint?

redo log 由来

引入了Buffer Pool 以后的确给数据的读写提高了效率。固然也同时带来了问题。
列如:
个人帐户余额有200块钱,发工资那天公司汇进来5000块钱。sql

update account set price = 5200 where id = 24
复制代码

咱们知道执行更新后,数据只是放在Buffer Pool 中,磁盘文件中仍是老数据。但是恰恰倒霉,这时候服务器断电了,内存中的数据一会儿就没有了。这可怎么办?到手的工资跑了。
固然了,Mysql 是不容许这种事情发生的,已经提交的事务,必须具备持久化能力。也就是针对上述状况,Mysql 必须保证更新语句若是成功,那么后续发生电点,崩溃等状况,服务器重启后数据还是修改完成后的数据。
为了作到这一点redo log 诞生了。能够说redo log为InnoDB 提供了可持久化的能力。
有了redo log ,上面的更新流程就变成了:数据库

  1. 修改Buffer Pool 对应页中的信息。(假设页已经存在在Buffer Pool中)
  2. 新增redo log 记上一笔:把id=24 的帐户的余额改成5200。 (固然实际状况可能还要复杂,好比要记录索引等等其余修改,顺带一条redo log 日志的类型在Mysql 5.7.21中有53种之多)
  3. 返回更新结果

这样,即便修改完成后,Buffer Pool 中的数据来不及刷入磁盘,数据库重启之时,仍是能够从redo log 中读取修改的内容,从新再作一遍一样的操做(redo)。保证了Buffer Pool 中的数据丢失还能找回来。服务器

为何redo log 的信息在崩溃的时候不会丢失?

redo log 是存放在磁盘的。app

  • innodb_log_group_home_dir 指定redo日志文件存放的目录。
  • innodb_log_file_size 指定每一个redo日志文件的大小。
  • innodb_log_files_in_group 指定redo日志的个数

redo log 能够存放的空间为:innodb_log_file_size × innodb_log_files_in_grouppost

那么问题来了,咱们知道Buffer Pool 是经过减小磁盘操做,从而提高性能的。如今为了保证持久性,写入redo log 仍是要进行磁盘操做,这样不是白费力了吗?
redo log 要进行磁盘操做这个是不可避免的,可是与Buffer Pool 磁盘随机写入比, redo log 的磁盘操做有几个优点: 1. 引入redo log buffer,按组写入,不是一条条写。 2. 磁盘为顺序写入。
固然也能够记住结论就是 redo log 日志的磁盘操做比起 Buffer Pool 的磁盘操做 性能要好不少。

redo log buffer

照搬Buffer Pool 的原理,redo log 也不是直接写入磁盘的,redo log 会先写入 redo log buffer 中,而后再写入磁盘。 那么问题又又又来了,怎么保证redo log buffer 中的信息在崩溃的时候不会丢失呢?
redo log buffer 的刷盘时机:性能

  • redo log buffer 空间不足的时候。
  • 事务提交的时候
  • 后台线程在不停的刷
  • 服务正常关闭的时候
  • checkpoint的时候

(能够比较下Buffer Pool 的刷盘时机,看看二者有什么不一样有什么相同)
从刷盘时机来看,redo log buffer的刷盘时机更为频繁,尤为是事务提交的时候这一条保证了提交的事务redo log 就已经存储到了磁盘中。
innodb_flush_log_at_trx_commit 取值范围 0,1,2
这个变量是用来控制事务提交的时候是否要刷新redo log buffer 到磁盘中。
0:标识事务提交不会向磁盘同步redo log。
1:默认值,每次提交事务向磁盘同步redo log。
2:每次提交事务将redo log 写到操做系统的缓冲区中,但没有真正写入磁盘。
这三种方式都各有利弊:
0: 虽然说按组批量顺序写入磁盘提升了很多磁盘操做效率,可是终归仍是有点性能损耗的,把变量设置成0,那么事务提交的时候就彻底避免了磁盘操做, 交由后台线程去刷新磁盘。 这样在大量频繁修改的业务场景的可以提高性能,可是一样要面对服务器挂了有数据丢失的风险。
1: 性能不如0,可是保证了提交的事务数据不丢失。
2: 性能介于0,1之间。能保证若是操做系统没挂,数据库挂了,事务的持久性还能保证,可是若是操做系统也挂了数据就会丢失。
(根据业务场景和服务器配置挑选合适的innodb_flush_log_at_trx_commit也能提高性能)spa

Checkpoint

上面已经提到redo log 的空间是有限的,例如咱们定义每一个文件大小为1G,文件数量为2个,那么redo log 最多能存储2G 大小的内容。因此会存在一种状况:修改内容较多,且事务持续时间很长(所谓的大事务),就会致使redo log 写满而没法写入。
在通常状况下,redo log 又是怎么工做的呢?
redo log 是一个环,经过擦除没用的信息达到空间的重复利用。 具体实现过程比较复杂,我这边只介绍下核心的思想,对具体实现有兴趣的朋友能够看 掘金小册:MysSQL是怎么运行的 第22章
什么是没用的信息呢?
咱们知道redo log 是为了防止Buffer Pool中的脏页丢失而设计的,那么若是随着系统运行,Buffer Pool 的脏页刷新到了磁盘中,那么redo log 对应的记录也就没用了。 一次checkpoint 的过程就是脏页刷新到磁盘中变成干净页,而后标记redo log 哪些记录能够被覆盖的过程。操作系统

总结

  • redo log 使用来保证InnoDB 的持久性的。
  • redo log 是保存在磁盘文件中的,可是经过按组,顺序写入的方式提高磁盘IO效率
  • redo log buffer 向磁盘刷入的时机更为频繁。能够经过innodb_flush_log_at_trx_commit控制事务提交是否刷盘。
  • redo log 因为空间有限,因此经过一次次的checkpoint 来标记能够覆盖的空间信息。

系列文章

Mysql 百问系列 : Join 会有哪几种工做方式?
Mysql 百问系列:Buffer Pool 是什么?线程

喜欢,支持欢迎关注公众号

相关文章
相关标签/搜索