Mysql日志系统(redo log与binlog)

275 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

Mysql数据库中,讲究日志先行策略,拿一条更新语句来说,离不开两个重要的日志模块,redo log和binlog。

redo log

当Mysql执行一个更新操作时,如果我们只在内存中更新了就视做提交成功,那么在写入磁盘前系统发生了崩溃,服务器重启后,这时内存的数据已经没了,磁盘也没有写入,数据就永久丢失了,这肯定不行。

如果我们在写入磁盘后才视作提交成功呢,我们知道写入磁盘是很耗时的,IO成本很高,而且对于InnoDB引擎,就算只更新了一个数据页的一个字节,它也需要刷新一个完整的额数据页。

那么怎么办呢,我们可以用一种临时文件来暂存数据,当执行一个事务的更新语句时,可以先写到这个临时文件中就视作提交成功,然后等合适的时机再刷入磁盘。这种临时文件就是redo log,它记录了事务对数据库做了哪些修改。它是固定大小的,从头开始写,写到末尾时就又回到开头循环写。

当写入redo log后,还没有刷入磁盘时,系统崩溃了,等系统重启后,仍会将redo log的数据刷入到磁盘页,所以也称作重做日志。

binog

DML语句除了会写redo log以外,还会写binlog, 它主要作用于主从复制,和备份恢复。

和redo log不一样的是它采用“追加写”的方式记录了所有的逻辑操作。当我们想恢复数据库到指定的某一秒,我们就可以取出最近一次的全量备份,然后从binlog里取出从全量备份到指定时间之间的这段日志,恢复到数据库上。

redo log和binglog的区别

这时,你一定会有个疑问,redo log和binlog为啥要并存呢,有一个不就行了吗?

因为binlog是先有的,属于MySQL Server层,并不仅限于InnoDB使用,其他引擎也可以使用,它的作用只能用于归档,做不到crash-safe(数据库发生异常重启,之前提交的记录都不会丢失),所以,InnoDB只能另外使用redo log来和binlog一起实现crash-safe。

redo log和binlog的区别主要有:

1、文件写入方式不同

  • binlog是追加写入,写满或实例重启后,会生成新的binlog 文件
  • redo log是循环写入

2、记录内容和记录内容的时间不同

  • binlog是逻辑日志,在commit时记录完毕后的语句的原始逻辑
  • redo log是物理日志,事务发起时就开始记录InnoDB表数据的变化

3、作用不同

  • binlog用于主从复制,恢复数据
  • redo log可用于异常宕机后的异常恢复

两阶段写入

写入redo log和binlog的流程,为了保证数据的一致,MySQL是通过两阶段来提交的。

两个阶段分为prepare阶段和commit阶段

  • prepare:事务语句先写入redo log buffer中,然后做一个事务准备提交标记,再将log buffer中的数据刷新到redo log,此时redo log状态为prepare。然后告知执行器执行完成了,随时可以提交事务。
  • commit:生成这个操作的binlog,刷入磁盘,执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交(commit)状态,更新完成。

一条更新语句的执行流程如下:

a.drawio.png