InnoDB 的 redo Log 和 刷盘
InnoDB 的数据都是存储在磁盘上, 每次读取数据都需要从磁盘加载, 为了提高IO速度,引入缓冲池(Buffer Pool),就是把磁盘上的数据(页)放到缓冲池中。下次读取相同的页会判断是不是在缓冲池中, 如果是就直接读取。
修改数据的时候,会先修改缓冲池里面的页。 缓冲池的数据(页)跟磁盘不一致时(即脏页),后台线程会将缓冲池的数据写入到磁盘中(即刷脏)
如果 Buffer Pool 里面的脏页还没有刷入磁盘时,数据库宕机或重启,数据将会丢失或不可用。
为了避免这个问题,引入了
redo Log
,用它来实现事务的持久性。刷盘的操作是随机I/O , 记录日志是顺序I/O。 为了提高I/O速度,减少寻道时间和旋转延迟时间,这里采用顺序I/O。
从缓存池写入到 redo log ,在刷到磁盘中
Buffer Pool 里的数据写入到 redo Log 中有三个时机
0 延迟写:log buffer 将每秒一次地写入log file 中,并且log file 的flush 操作同时进行。
- 该模式下,在事务提交的时候,不会主动触发写入磁盘的操作。
1 (默认)实时:每次事务提交时都会将 log buffer 的数据写入 到 log file ,并且刷到磁盘中。
2 实时写,延迟刷:每次事务操作会将 log buffer 的数据写入到 log file 中,但是 flush 操作并不会同时进行。
- 该模式下mysql 会每秒执行一次 flush 操作。
undo Log
undo Log 回滚日志,记录事务发生前的数据状态,如果修改数据时出现异常,可以用 undo Log 来实现回滚操作(保持原子性)
Bin Log
Bin Log 二进制日志, 记录了对 MySQL数据库执行更改的所有操作(不包括SELECT 、SHOW 这类操作) ,可以用来做主从复制和数据恢复(把binLog 文件导出成 SQL 语句,重新执行)。
跟 redo Log 日志不一样, 他的文件内容可以追加,没有固定大小限制。
当执行事务操作时 redo Log 、undo Log 和 bin Log 的变化
- 查询出来数据,对数据进行修改
- 将修改的数据写入到 Buffer Pool 中, 并写入到 redo log ,这时 redo log 进入prepare 状态,
- 然后告诉执行器,执行完成了,可以随时提交。
- 执行器收到通知后记录 binlog,然后调用存储引擎接口,设置 redo log 为commit状态。
- 最后更新完成。
会先写到内存的buffer pool 里面,同时记录redo log,如果在刷盘之前出现异常,在
重启后就可以读取redo log 的内容,写入到磁盘,保证数据的持久性。