开启掘金成长之旅!这是我参与「掘金日新计划 · 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)状态,更新完成。
一条更新语句的执行流程如下: