概述
在MYSQL中,日志是非常重要的,其中Redo log 和undo log都是引擎层(innodb)实现的日志,redo log 是重做日志,提供 前滚 操作,undo log 是回退日志,提供 回滚 操作。
- redo Log是数据库引擎的一种日志,用于记录数据库的物理变更操作,例如数据页的修改。它以顺序方式记录,通常是追加写入磁盘上的日志文件。
- undo Log是数据库引擎的一种日志,用于记录事务的回滚信息,即撤销已提交事务所做的修改操作。它记录了事务执行过程中旧值的备份,以支持事务的回滚操作。
回滚
未提交的事务,即事务未执行 commit。但事务内修改的脏页中,有一部分已刷盘。此时数据库宕机重启,需要回滚来将先前那部分已经刷盘的脏块从磁盘上撤销。
前滚
未完全提交的事务,即事务已经执行 commit,但该事务内修改的脏页中只有一部分数据被刷盘,另一部分还在 buffer pool,此时数据库宕机重启,就要用前滚来将未来得及刷盘的数据从 redo log 中恢复出来并刷盘。
Redo Log
MySQL 数据存在磁盘中,每次读写数据需做磁盘随机IO,并发场景下性能差。对此 MySQL 引入缓存 Buffer Pool 做优化。其包含磁盘中部分数据页(page)的映射,来缓解数据库的磁盘压力。
- 缓冲池(bufer pool):主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度
- 数据页(page):是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。页中存储的是行数据
这个缓存中包含了磁盘中部分数据页(page
)的映射,以此来缓解数据库的磁盘压力。当从数据库读数据时,首先从缓存中读取,如果缓存中没有,则从磁盘读取后放入缓存;当向数据库写入数据时,先向缓存写入,此时缓存中的数据页数据变更,这个数据页称为脏页,Buffer Pool
中修改完数据后会按照设定的更新策略,定期刷到磁盘中,这个过程称为刷脏页。
MySQL由于某些原因宕机重启,此时Buffer Pool
中修改的数据还没有及时的刷到磁盘中,就会导致数据丢失,无法保证事务的持久性。为了解决这个问题引入了redo log
日志文件由两部分组成:重做日志缓冲(redo log bufer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。
redo log
用到了WAL
(Write-Ahead Logging)技术,这个技术的核心就在于修改记录前,一定要先写日志,并保证日志先落盘,才能算事务提交完成。有了redo log再修改数据时,InnoDB引擎会把更新记录先写在redo log中,在修改Buffer Pool
中的数据,当提交事务时,调用fsync
把redo log刷入磁盘。至于缓存中更新的数据文件何时刷入磁盘,则由后台线程异步处理
redo log 采用大小固定,循环写入的方式,当写满后,会重新从头开始循环写,类似一个环状。这样设计原因是 redo log 记录的是数据页上的修改,如果 Buffer Pool 中数据页已经刷到磁盘,这些记录就失效了,新日志会将这些失效的记录覆盖擦除。
注意:redo log 满了,在擦除之前,要确保这些要被擦除记录都已经刷到磁盘中了。在擦除旧记录释放新空间期间,不能再接收新的更新请求,此时 MySQL 性能会下降。因此高并发情况下,合理调整 redo log 大小很重要。
Undo Log
undo Log(回滚日志)是MySQL中的一种重要数据结构,用于实现事务的ACID特性中的"Atomicity"(原子性)和"Isolation"(隔离性)。
事务提交成功由redo log保证数据持久性,而事务可以进行回滚从而保证事务操作原子性则是通过undo log 来保证的。
undo log产生和销毁:Undo Log在事务开始前产生;事务在提交时,并不会立刻删除undo log,innodb会将该事务对应的undo log放入到删除列表中,后面会通过后台线程purge thread进行回收处理
- 事务A执行update更新操作,在事务没有提交之前,会将旧版本数据备份到对应的undo buffer中,然后再由undo buffer持久化到磁盘中的undo log文件中, 之后才会对user进行更新操作,然后持久化到磁盘
- 在事务A执行的过程中,事务B对User进行了查询
在Mysql里数据每次修改前,都首先会把修改之前的数据作为历史保存一份到undo log里面的,数据里面会记录操作该数据的事务ID,然后我们可以通过事务ID来对数据进行回滚。
可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
总结
redo log日志记录的是数据页的物理变化,服务宕机可用来同步数据,而undo log 不同,它主要记录的是逻辑日志,当事务回滚时,通过逆操作恢复原来的数据,比如我们删除一条数据的时候,就会在undo log日志文件中新增一条delete语句,如果发生回滚就执行逆操作。
redo log保证了事务的持久性,undo log保证了事务的原子性和一致性