4.3 redo log
目录
4.3 redo log
4.3.1 redo log 介绍
4.3.2 redo log 的作用
4.3.3 redo log file 结构
4.3.4 redo log 提交逻辑
4.3.5 redo log 持久化逻辑
4.3.6 redo log 检查点
4.3.7 小结
未完待续....
上文我们学习了表空间,下面我们来介绍日志系统,InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性。
InnoDB存储引擎使用专门的日志文件来存储重做日志(Redo Log),而不是将其保存在表空间内。这些文件称作redo log files,它们是确保事务的持久性和支持数据库崩溃恢复机制的核心部分。Redo log buffer中的数据会定期刷新到这些日志文件中,从而实现数据的持久化。
redo log文件通常有两个或更多,它们以ib_logfile0、ib_logfile1等形式存在,并可以在MySQL的数据目录中找到,该目录通常由<datadir>配置指定。这些文件的大小(innodb_log_file_size)和数量(innodb_log_files_in_group)可在MySQL的配置文件中设置。配置这些日志文件时,需要平衡事务的长短,以及崩溃恢复所需的时间。重做日志性能对InnoDB的整体性能有显著影响,主要取决于磁盘的I/O性能。置于高速磁盘如SSD上的重做日志文件可以提升数据写入速度,而足够大的重做日志缓冲区(由innodb_log_buffer_size配置)则能减少磁盘写入频率,从而优化性能。(这通常需要专业的文件存储知识)
4.3.1 redo log 介绍
InnoDB存储引擎通过重做日志文件(通常简称为redo log)来确保事务的持久性,并支持数据库在崩溃后的恢复。纪录事务的变更,这些变更会先写入到内存的重做日志缓冲区,然后在事务提交时刷新到磁盘上的重做日志文件中。这种基于预写日志协议(Write-Ahead Logging, WAL)的过程确保了,即使数据库崩溃,事务的更改仍然安全且可以被重放以恢复数据库。
redolog 在性能上的贡献就是将随机存储转化为顺序存储,加速数据修改提交的速度;通过定时刷盘策略,在引擎不忙的时候将redo log的数据刷回磁盘。这样的策略能够提高峰值的写入速度从而提高引擎的性能。
redolog 在 MySQL中使用固定大小的循环结构,它仅记录那些尚未持久化到磁盘的数据更改。一旦这些更改被成功刷新(写入)到磁盘上,相关的日志信息就会被标记为可以覆盖,以便为新的数据更改腾出空间。
4.3.2 redo log 的作用
InnoDB存储引擎采用了两层存储架构,一层是速度较慢的持久化存储设备(如磁盘),另一层是速度较快的主存储器(RAM)。为了减少对慢速持久存储的访问频率,数据页会被缓存到快速的内存中。当需要重新访问这些数据时,系统可以直接从内存中获取数据页的副本,而无需从磁盘读取,从而提高数据访问效率。
- 换入:将未缓存的页从磁盘家在进来的过程称为换入。
- 换出:如果可用空间不足以放下页,则某些页会被移除缓存,刷回到磁盘。如果页的内容与磁盘是同步的(已经刷写过或未改动过)并且该页未被引用,则可立即换出。如果当前页是脏页,则必须在刷写后才能换出,如果当前页正在被引用则不允许换出
- 脏页:在缓存中的页如果被修改,但还未刷回到磁盘,就称这些页为脏页。
所有对缓冲区的更改都保留在内存中,直到最终被写回到磁盘上,由于不允许任何其他进程修改磁盘上的这些文件,所以这个同步过程是单向的。只能是内存--》磁盘,而不能反过来进行。页缓存让数据库更好的控制内存管理和磁盘访问。
缓存设计的另一个比较重要的问题是持久性的问题,如果数据库崩溃,则未刷写的数据都会丢失,为了确保所有更改都被持久化,redolog的检查点机制和刷脏策略会协同工作,将脏页刷新到磁盘中,而后对应的redolog记录才会被丢弃。可以看出 redolog 就专门解决崩溃后数据恢复的问题。
4.3.3 redo log file 结构
redo log file 记录的是数据记录的逻辑变化,而不是物理变化
逻辑变化指的是数据记录的抽象变化,例如一条SQL语句的执行结果。例如,
UPDATE table SET column='value' WHERE id=1;
这条语句的逻辑变化是“将id为1的记录的列column的值更改为'value'”。物理变化则涉及到数据存储在磁盘上的实际物理位置的变化。物理变化会涉及到具体的数据页和字节偏移等细节。
每个Log Record通常包含以下部分:
- Log Sequence Number (LSN):一个唯一的序列号,表示日志记录在redo log文件中的位置。
- Table ID:引起页面变更的表的标识符。
- Page Number:变更发生在数据库哪个页上。
- Data Before Change:变更前的数据,可以用于回滚操作。
- Data After Change:变更后的数据,用于恢复操作。
- Other Info:其他重要信息,如事务ID,类型(insert、update、delete)等。
上述内容是一个概念性描述,帮助读者理解redolog的结构和工作原理。实际的InnoDB重做日志格式会更加复杂和专门化,包括压缩和优化,以提高存储效率和恢复性能。重做日志文件是二进制格式,一般无法直接阅读。在实际应用中,管理员需要使用专业工具来查看或分析这些日志。
4.3.4 redo log 提交逻辑
redolog在事务操作过程中存在两种不同的状态,prepare和commit状态,也就是我们通常说的二段提交
1、事务在操作阶段:例如执行了一条sql语句后,没提交时,这条语句相应的redolog会被写入,log记录首先会存储在logbuffer中,这时对应的binlog也会被写入,稍后会进行刷盘。(这时redolog处于prepare状态)
2、事务在提交准备阶段:InnoDB会保证redolog和binlog都持久化到磁盘上,然后再进行事务提交。(通过操作系统的fsync系统调用)
3、事务在最终提交阶段:InnoDB会将事务标记为已完成,并在redolog中写入提交commit标记,这时redolog 中 commit不一定立即刷回到磁盘,这取决于innodb_flush_log_at_trx_commit的配置(下文会讲)。(这时redolog处于commit状态)
4、事务在回滚阶段:事务回滚,redolog不会发生变化,有读者可能会提出疑问,如果不变化崩溃恢复的时候不就数据不一致了吗,其实在binlog中,每个事务结束时都会有一个特殊的事件(event)来表示事务的结束。这通常是一个XID event(用于提交事务)或者 ROLLBACK event(用于回滚事务)。如果事务成功提交,会在binlog中记录一个XID event,表示这个事务已经成功完成并需要被复制和应用到从库(slave)上。如果事务回滚,则会在binlog中记录一个ROLLBACK event,表示这个事务被回滚,从库在重放日志时也应该回滚这个事务。所以即使redolog不进行修改,数据也能保证一致性。
4.3.5 redo log 持久化逻辑
redo log存在如下三种存储状态
这三种状态分别是:
1、存在 redo log buffer 中,物理上是在 MySQL 进程内存中,就是图中的蓝部分;
2、写到磁盘 (write),但是没有持久化(fsync),物理上是在文件系统的 page cache 里面,也就是图中的绿色部分;
3、持久化到磁盘,对应的是 hard disk,也就是图中的紫色部分。日志写到 redo log buffer 是很快的,wirte 到 page cache 也差不多,但是持久化到磁盘的速度就慢多了。
通过上图我们知道了,为了性能,事务执行完成时 redo log数据有可能还在log buffer中或者pageCache中,那么什么时候,这些日志数据会确定被刷回磁盘呢?以下列出了一些Redolog持久化的时机
事务提交时:innodb_flush_log_at_trx_commit = 1时,当一个事务被提交,其对应的所有修改必须被写入redo log,以确保即使数据库发生崩溃,也能够通过重做日志来恢复这些修改。这是遵循ACID原则中的持久性(Durability)。
InnoDB存储引擎通过innodb_flush_log_at_trx_commit参数控制redo log的刷新策略,该参数有三个设置选项:
- 当设置为0时,事务在提交时不会立即将redo log写入磁盘,而是保留在redo log buffer中。这些日志由后台进程每秒刷新到磁盘一次。这意味着在数据库实例崩溃的情况下,最多可能会丢失最后一秒内的事务数据。
- 当设置为1时,事务提交会伴随每次redo log的同步持久化到磁盘操作。具体来说,每个事务提交都会执行一个fsync操作。这是最为保守的设置,即便发生系统宕机,已提交的事务也不会丢失。
- 当设置为2时,事务提交只会将redo log写入系统的page cache,并不保证立即写入磁盘。这种配置下,事务提交时仅涉及write操作,因此在数据库实例崩溃时不会丢失事务,但如果发生系统宕机,仍有可能导致已提交事务的丢失。
通常,redo log的持久化程度越高,对性能的影响也越大。在标准操作中,推荐将innodb_flush_log_at_trx_commit的值设置为1,以确保数据的完整性和安全性。然而,在面临系统高负载的高峰时段,可以临时将其调整为2以提高性能,尽管这样做会稍微增加数据丢失的风险。
InnoDB允许多个事务并发地将日志复制到log buffer。因此,当单个事务提交并触发redo log写入文件时,可能会隐式地同时将其他事务的redo log也写入,这就实现了所谓的“组提交”(group commit)机制,它可以优化日志写入操作,提高整体吞吐量。
除了事务提交还有如下几个情况会导致redo log记录被刷到磁盘上
- 定期刷新:在事务运行过程中,数据库会定期将缓存中的redo log写入到磁盘上的redo log文件中。这是由InnoDB存储引擎的内部刷新机制决定的,通常是为了释放redo log buffer中的空间,或由于其他触发了刷新的操作,如长时间运行的事务。
- 缓冲池不足时:如果InnoDB的redo log buffer(内存中的缓冲区)接近满载,那么系统会自动将缓冲区的内容刷新到磁盘上,即使事务尚未提交。
- 检查点发生时:InnoDB通过创建检查点(checkpoint)来减少崩溃恢复时间,这涉及将当前记载在redo log中的所有数据修改同步到磁盘上的数据文件。此时,redo log同时也会被写入磁盘。
Redo log的写入策略旨在平衡性能与数据持久性。频繁的写入可以降低数据丢失的风险,但可能会对性能产生负面影响,特别是当磁盘I/O成为瓶颈时。相反,较少的写入可以提高性能,但在发生崩溃的时候可能导致更多的数据丢失。数据库管理员经常需要根据具体的应用场景和性能要求来调整redo log的配置和写入策略。
4.3.6 redo log 检查点
之前我们提到过数据库崩溃时,则未刷写的数据都会丢失,而redolog检查点机制和刷脏策略会协同工作,将脏页刷新到磁盘中。检查点(Checkpoint)是Redo Log系统中的一个关键概念,用于优化日志处理并减少系统崩溃恢复的时间。redologfile是一个可以被复用的文件环。
而设置检查点的主要目的是:
- 限制Redo Log的大小:由于Redo Log通常是固定的大小,并采用循环利用的方式,检查点帮助确定哪些Redo Log记录不再需要(因为相关的脏页已经被持久化到磁盘上),从而可以被重用。
- 减少崩溃恢复时间:在发生崩溃时,恢复过程只需要从最近的检查点开始应用Redo Log记录,而不是从头开始。这样可以显著减少恢复所需的时间。
InnoDB维护了检查点的位置,该位置是Redo Log中的一个标记点,表示到此为止的所有数据页的修改都已被写入到了磁盘上。这意味着,Redo Log中位于检查点之前的部分可以被标记为不再需要,并且在Redo Log空间满时可以被覆盖。
检查点的变化通常是自动发生的,并且是由InnoDB存储引擎根据多种因素来决定:
- 当缓冲池中脏页的数量达到一定阈值时。
- 在特定的时间间隔内(比如每秒钟或者每分钟)。
- 当Redo Log的空间使用接近其配置的限制时。
检查点操作的主要过程通常包括以下步骤:
- 选择检查点位置:InnoDB选择一个Redo Log序列号(LSN),确保此位置之前的所有事务都已被写入磁盘。
- 刷新脏页:InnoDB将所有LSN小于或等于检查点LSN的缓冲池中的脏页刷新到磁盘。
- 记录检查点:检查点信息(包括LSN)被写入到一个特定的系统表空间文件中,以便在数据库启动时进行参考。
通过这种方式,检查点机制帮助InnoDB存储引擎平衡了性能和数据完整性的要求,确保事务的ACID属性,同时提高了系统的整体效率。
4.3.7 小结
本文主要描述了InnoDB存储引擎中重做日志(redo log)的功能、结构和作用。redo log如何用于确保事务的持久性,并在数据库崩溃后提供恢复能力。它还详细介绍了redo log文件的存储位置、配置方法以及如何通过预写式日志协议(WAL)记录事务变更。此外,内容还涉及了redo log的二阶段提交过程、持久化策略、文件结构和检查点(checkpoint)机制。
Redo Log Files 存储
重做日志在表空间外单独存储,位于称为redo log files的专用文件中。这些文件,通常命名为ib_logfile0、ib_logfile1等,位于MySQL的数据目录<datadir>下。Redo log files的尺寸(由innodb_log_file_size参数控制)和文件数量(由innodb_log_files_in_group参数控制)可以配置,以确保处理效率与恢复速度的平衡。
Redo Log 的职责
Redo log利用预写式日志协议(WAL)记录事务更改,首先将这些更改写入内存中的redo log buffer,然后在适当的时机刷新到磁盘上。这个机制不仅保证了事务的持久性,还将I/O操作由随机写变为顺序写,提高了数据提交的速度。适当配置redo log对于提升InnoDB的性能至关重要。
持久化策略
在事务的操作过程中,redo log遵循二阶段提交协议,即prepare和commit阶段。innodb_flush_log_at_trx_commit参数定义了何时将redo log buffer中的数据持久化到磁盘,这直接关系到系统在崩溃时能够恢复多少数据。
Redo Log文件的结构
Redo log文件包含一系列格式化的日志记录,每个记录包含LSN、表ID、页码以及事务变更前后的数据等信息。由于redo log的二进制格式,通常需要专业工具来进行阅读和分析。
检查点机制
检查点是InnoDB日志系统中的一个高效机制,用于标记在某一点所有修改都已写入磁盘。它限制了redo log的空间需求,并在系统崩溃时缩短了数据恢复时间。通过自动设置检查点,InnoDB有效地平衡了性能和数据完整性的需求。