mysql 的日志类型:
redo log 适用于崩溃恢复(crash-safe)
事务的四大特性里面有一个是 持久性 ,具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态 。那么 mysql是如何保证一致性的呢?最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题,主要体现在两个方面:
(1)因为 Innodb 是以页为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了!
(2)一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!
因此mysql设计了redo log, 具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。
redo log
包括两部分:
一个是内存中的日志缓冲(redo log buffer )
另一个是磁盘上的日志文件( redo logfile )。 mysql 每执行一条DML语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。
这种 先写日志,再写磁盘 的技术就是MySQL里经常说到的WAL(Write-Ahead Logging)技术。
在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。因此, redo log buffer 写入 redo log file 实际上是先写入 OS Buffer ,然后再通过系统调用 fsync()
将其刷到 redo log file 中,过程如下:
MySQL支持用户自定义在commit时如何将log buffer中的日志刷log file中。这种控制通过变量 innodb_flush_log_at_trx_commit 的值来决定。该变量有3种值:0、1、2,默认为1。但注意,这个变量只是控制commit动作是否刷新log buffer到磁盘。
在主从复制结构中,要保证事务的持久性和一致性,需要对日志相关变量设置为如下:
前面说过, redo log
实际上记录数据页的变更,而这种变更记录是没必要全部保存,因此 redo log
实现上采用了大小固定,循环写入的方式,当写到结尾时,会回到开头循环写日志。如下图:
在innodb中,既有redo log 需要刷盘,还有数据页也需要刷盘, redo log 存在的意义主要就是降低对数据页刷盘的要求 。
(1) write pos 表示 :redo log 当前记录的 LSN (逻辑序列号)位置
(2)check point 表示:数据页更改记录刷盘后对应redo log所处的LSN(逻辑序列号)位置
(3)write pos 到 check point 之间的部分是 redo log 空着的部分,用于记录新的记录;
(4) check point 到 write pos 之间是redo log 待落盘的数据页更改记录。当write pos 追上check point时,会先推动check point 向前移动,空出位置再记录新的日志。
有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。
redo log日志的大小是固定的,即记录满了以后就从头循环写。
图片来自极客时间,该图展示了一组4个文件的redo log日志,checkpoint之前表示擦除完了的,即可以进行写的,擦除之前会更新到磁盘中,write pos是指写的位置,当write pos和checkpoint相遇的时候表明redo log已经满了,这个时候数据库停止进行数据库更新语句的执行,转而进行redo log日志同步到磁盘中。
LSN实际上就是InnoDB使用的一个版本标记的计数,它是一个单调递增的值。数据页和redo log都有各自的LSN。我们可以根据数据页中的LSN值和redo log中LSN的值判断需要恢复的redo log的位置和大小。
redo log | binlog | |
---|---|---|
文件大小 | redo log 的大小是固定的。 | binlog 可通过配置参数 max_binlog_size 设置每个binlog 文件的大小。 |
实现方式 | redo log 是 InnoDB 引擎层实现的,并不是所有引擎都有。 | binlog 是Server层实现的,所有引擎都可以使用 binlog 日志 |
记录方式 | redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。 | binlog通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上 |
适用场景 | redo log 适用于崩溃恢复(crash-safe) | binlog 适用于主从复制和数据恢复 |
参考:
https://zhuanlan.zhihu.com/p/35355751
https://dev.mysql.com/doc/refman/5.7/en/innodb-redo-log.html
http://mysql.taobao.org/monthly/2015/05/01/
https://segmentfault.com/a/1190000023827696
https://blog.csdn.net/u010002184/article/details/88526708
原文:https://www.cnblogs.com/shix0909/p/15093593.html