这是我参与更文挑战的第4天,活动详情查看:更文挑战
一、前言
相关概念:
redo logbinlog
redo log,是一种偏向物理性质的重要日志,记录着 “对哪个数据页中的什么记录,做了什么修改”。
redo log 本身是属于 InnoDB 存储引擎特有的一个东西。
binlog 叫做归档日志,里面记录的是偏向于逻辑性的日志,类似于 “对 user 表中 id=10的一行数据做了更新操作,更新以后的值是什么”
binlog 不是 InnoDB存储引擎特有的日志文件,是属于 MySQL Server的日志文件。
提交事务的时候,同时会写入 binlog:
提交事务的时候,会把
redo log日志写入磁盘文件中去,然后其实在提交事务的时候,还会把这次更新对应的binlog日志写入到磁盘文件中去。
如图:
图中的 执行器,负责跟 InnoDB 进行交互,包括从磁盘里加载数据到 Buffer Pool中进行缓存、写入 undo日志、更新 Buffer Pool里的数据,以及写入 redo log buffer,redo log 刷入磁盘,写 binlog 等等。
步骤 5, 6 是提交事务开始的时候,属于提交事务的阶段。
二、binlog 日志的刷盘策略分析
binlog日志,也有不同的刷盘策略,有一个 **sync_binlog**参数可以控制 binlog的刷盘策略,默认值 0。
sync_binlog 参数值:
- 0, 此时
binlog写入磁盘的时候,不会直接进入磁盘文件,而是进入os cache内存缓存。 - 1, 此时会强制在提交事务的时候,把
binlog直接写入到磁盘文件里。
基于 binlog 和 redo log 完成事务的提交:
当把
binlog写入磁盘文件之后,接着就会完成最终的事务提交,此时会把本次更新对应的binlog文件名和这次更新的binlog日志在文件里的位置,都写入到redo log日志文件里去,同时在redo log日志文件里写入一个commit标记。
如图:
事务提交完成标准:5、6、7三个步骤都执行完毕。
此时,会有如下情况:
redo写入磁盘文件之后,MySQL宕机了
这个时候因为没有最终的事务
commit标记在redo日志里,所以此次事务可以判定为不成功。不会说
redo日志文件里有这次更新的日志,但是binlog日志文件里没有这次更新的日志,不会出现数据不一致的问题。
redo写入磁盘文件之后,binlog日志写入磁盘,MySQL宕机了
因为
redo log中的没有最终commit标记,因此此时事务提交也是失败的。
三、更新数据
后台
IO线程随机将内存更新后的脏数据刷回磁盘
MySQL 有一个后台的 IO 线程,会在之后某个时间里,随机的把内存 buffer pool中的修改后的脏数据给刷回到磁盘上的数据文件里。
如图:
此时,崩溃会怎样?
在
IO线程把脏数据刷回磁盘之前,哪怕MySQL宕机崩溃也没关系,因为重启之后,会根据redo日志恢复之前提交的事务更新到内存里去。
问题:为什么修改磁盘里的数据,要通过 IO线程不定时的去执行?
异步操作,加快操作执行。