MySQL学习笔记
redo log
1. 什么是WAL(Write-Ahead Logging)
1.1 百度百科:
预写日志系统
数据库中一种高效的日志算法,对于非内存数据库而言,磁盘I/O操作是数据库效率的一大瓶颈。
在相同的数据量下,采用WAL日志的数据库系统在事务提交时,磁盘写操作只有传统的回滚日志的一半左右,大大提高了数据库磁盘I/O操作的效率,从而提高了数据库的性能
(说了跟没说一样)
1.2 大白话说就是:
- 所有写操作,先写到日志中,再去修改具体的数据
举个例子:
- 设磁盘
a扇区
存了一个数据b=1
,现在我想改成b=2
- 按照WAL的思路,我不会直接修改
a扇区
的内容 - 而是将修改
b=2
这个操作,保存在一个日志文件中,等系统空闲的时候,再去修改a扇区
2. 什么是redo log
redo log
就是MySQL的InnoDB引擎使用的WAL机制的具体实现
MySQL是这么做的:
- 当有一条记录需要更新的时候
- InnoDB 引擎就会先把记录写到 redo log 里面,并更新内存,这个时候更新就算完成了。(redo log 记录下数据块的改动)
- 同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做
3. 为什么要用redo log
3.1. 提高写效率
- redo log 只保存没有刷新到磁盘上的操作内容, 写的是一个连续的硬盘空间, 硬盘的顺序读写, 要比4k随机读写快太多了
找个表格看看(表格表示的是数量级上的区别,不是具体的读写速度)
延迟 | 顺序读写速度 | 4k随机读写速度 | |
---|---|---|---|
机械硬盘 | 2500000ns | 100MB/s | 1MB/s |
固态硬盘 | 15000ns | 1000MB/s | 10MB/s |
内存 | 100ns | 10000MB/s | 500MB/s |
L3 cache | 1ns | >100000MB/s | >100000MB/s |
(1,000,000纳秒=1毫秒)
3.2. 保证crash-safe
- 即使数据库发生异常重启,之前提交的记录都不会丢失
- 当数据库重启的时候,可以根据redo log恢复之前提交的事务
4. redo log 是怎么保存数据的?
- InnoDB 的 redo log 是固定大小的
- 比如可以配置为一组 4 个文件,每个文件的大小是 1GB
- 那么这块硬盘空间总共就可以记录 4GB 的操作。
- 从头开始写,写到末尾就又回到开头循环写
4.1 保存形式
- 物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file的物理文件中去的。
redo log
是以循环写的方式来在日志文件中写入的write pos
是当前记录的位置,一边写一边后移。checkpoint
是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。write pos
和checkpoint
之间的是redo log
上还空着的部分,可以用来记录新的操作。- 如果
write pos
追上checkpoint
,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把checkpoint
推进一下。
redo log 一般保存在日志文件 ib_logfile0 和 ib_logfile1 这种文件中
修改 ib_logfile 的 个数 和 大小 以及 存放路径:
可以通过参数innodb_log_files_in_group来改变文件个数,这个参数的默认值是2;
可以通过参数innodb_log_file_size来指定每个redo日志的大小;
可以通过参数innodb_log_group_home_dir指定redo日志所在的目录。
4.2 如何保存数据到redo log
有这些场景会将redo log buffer
写入 redo log
:
- 当事务commit的时候,
redo log buffer
的内容会被写入redo log
- InnoDB 有一个后台线程,每隔 1 秒,就会把
redo log buffer
中的日志,调用 write 写到文件系统的page cache
,然后调用fsync
持久化到磁盘。 redo log buffer
占用的空间即将达到innodb_log_buffer_size
一半的时候,后台线程会主动写盘- 并行的事务提交的时候,顺带将这个事务的 redo log buffer 持久化到磁盘
- 当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。