引入
在介绍redo log和undo log之前,我们需要了解 MySQL 中的两个概念:缓冲池
和数据页
。
缓冲池(buffer pool)
:主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行 CRUD 操作时,先操作缓冲池中的数据(若缓冲池中没有数据,则从磁盘加载并缓存),以一定频率刷新到磁盘,从而减少磁盘 IO,加快处理速度
数据页(page)
:是 InnoDB 存储引擎磁盘管理的最小单元,每个页大小 16KB,页中存储的是行数据
那么这两个东西有什么作用呢?我们看下面这张图:
当我们执行操作提交了事务之后,我们操作的是 MySQL 中的数据,为了提升性能,引入了两块区域,第一个是内存结构
,第二个是磁盘结构
。内存结构呢就是我们上面说的buffer pool,磁盘结构里面存储的是数据页(page),每个页中存储的就是我们表中的一行一行的数据,有时候可能好几个数据页存储一个表的数据。
当我们去操作数据时,并不会直接操作磁盘,而是首先操作内存(buffer pool),操作内存性能会很高。当我们操作完数据后,会以一定的频率把数据同步到磁盘中去。但是,这就会出现问题,假如我们操作完数据(深橙色
)准备同步到磁盘中,此时宕机了,那么就会失败,内存中的数据就丢失,磁盘中的数据也丢失了,这就违背事物的特性持久化。所以 MySQL 中引入了日志文件 redo log
什么是 redo log?
redo log 是重做日志,记录的是事务提交时数据页的物理修改,用来实现事务的持久性
redo log 由两部分组成:重做日志缓冲(redo log buffer)和重做日志文件(redo log file)。前者是在内存中,后者在磁盘中。当事务提交后会把所有修改信息存到该日志文件中,用于刷新脏页(内存中修改过的文件叫做脏页)到磁盘,发生错误时进行数据恢复使用。
如上图所示:当 buffer pool 中的数据被修改之后,会同步到内存中的 redo log buffer 中去,然后在某个时间点再会一次性同步到磁盘中的 redo log file 中去。这种先写日志,再写磁盘技术就是我们说到的 WAL(Write-Ahead Logging)技术。
可能会有疑惑,那为什么不直接同步磁盘呢?是因为这会有很大的 IO 消耗,性能十分低下
详解解释内容点这里
undo log
undo log 是回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和 MVCC(多版本并发控制)。undo log 记录的是逻辑日志,redo log 记录的是物理日志
逻辑日志和物理日志区别
逻辑日志:简单理解为记录的就是 SQL 语句
物理日志:因为 MySQL 数据最终是保存在数据页中的,物理日志记录的就是数据页变更
当删除一条语句时,undo log 中会记录一条对应的 insert 记录,反之亦然;
当更新一条记录,它记录一条对应相反的更新记录。执行回滚时,就可以从 undo log 中的逻辑记录读取到对应的内容并回滚。undo log 可以实现事务的一致性和原子性