MySQL学习笔记(4)三大日志
本文参考:https://javaguide.cn/database/mysql/mysql-logs.html
三大日志
MySQL中的三大日志分别为:binlog(归档日志)、redo log(重做日志)、undo log(回滚日志)。
redo log
主要作用:
redo log 是InnoDB引擎独有的,他让MySQL拥有了崩溃恢复的能力。在发MySQL服务宕机了或者实例挂了之后,服务重启时,InnoDB通过redo log恢复数据,保证数据的持久性和完整性。
redo log储存的核心内容
- 表空间号(Space ID):标识数据页所属的表空间。
- 数据页号(Page Number):标识具体的数据页。
- 偏移量(Offset):在数据页内的具体位置。
- 修改数据长度(Length):修改操作涉及的数据长度。
- 具体修改的数据(Data):实际修改的内容。
写入方式
MySQL 中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到Buffer Pool中。后续的查询都是先从 Buffer Pool 中找,没有命中再去硬盘加载,减少硬盘 IO 开销,提升性能。更新表数据的时候,也是如此,发现 Buffer Pool 里存在要更新的数据,就直接在 Buffer Pool 里更新。然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到 redo log 文件里。
在MySQL的InnoDB存储引擎中,数据写入和redo log写入的时机以及它们之间的关联
在MySQL的InnoDB存储引擎中,数据写入和redo log写入的时机以及它们之间的关联如下:
数据写入的时机
- 数据页修改:当事务对数据进行修改时,数据页会在内存中的Buffer Pool里被修改,并不会立即写入磁盘。
- 刷盘时机:数据页的刷盘主要依赖于检查点(Checkpoint)机制。检查点会定期将内存中的脏数据(已修改但尚未写入磁盘的数据页)刷新到磁盘,以减少恢复时间。
redo log的刷盘时机
- 事务提交:当事务提交时,redo log会被刷盘,确保已提交事务的数据修改在磁盘上持久化。
- log buffer空间不足:当redo log buffer中的记录写入量大于其内存空间的一半时,会触发落盘。
- 后台线程定时刷:InnoDB的后台线程每隔1秒会将redo log buffer中的内容写入磁盘。
- 正常关闭服务器:在MySQL正常关闭时,redo log会被刷盘。
- Checkpoint:在检查点操作时,redo log也会被刷新到磁盘。
由于后台线程的存在,一个未提交的事务的redo log也可能被刷入盘中。重启后需要使用redo log与undo log结合来恢复数据 。
两者的关联
- redo log先于数据页写入:redo log的写入在数据页修改之后、数据页刷盘之前。这样即使在数据页未写入磁盘之前系统崩溃,也能通过redo log恢复数据。
- 确保数据一致性:redo log的写入机制确保了在事务提交时,数据修改已经被记录,即使数据页尚未写入磁盘,也能在恢复时通过redo log重新应用这些修改,保证数据的一致性和完整性。
控制redo log刷盘时机的参数(innodb_flush_log_at_trx_commit)
- 0:设置为 0 的时候,表示每次事务提交时不进行刷盘操作。这种方式性能最高,但是也最不安全,因为如果 MySQL 挂了或宕机了,可能会丢失最近 1 秒内的事务。
- 1:设置为 1 的时候,表示每次事务提交时都将进行刷盘操作。这种方式性能最低,但是也最安全,因为只要事务提交成功,redo log 记录就一定在磁盘里,不会有任何数据丢失。
- 2:设置为 2 的时候,表示每次事务提交时都只把 log buffer 里的 redo log 内容写入 page cache(文件系统缓存)。page cache 是专门用来缓存文件的,这里被缓存的文件就是 redo log 文件。这种方式的性能和安全性都介于前两者中间。
redo log日志文件组
- write pos 是当前记录的位置,一边写一边后移
- checkpoint 是当前要擦除的位置,也是往后推移每次刷盘 redo log 记录到日志文件组中,write pos 位置就会后移更新。
- 每次 MySQL 加载日志文件组恢复数据时,会清空加载过的 redo log 记录,并把 checkpoint 后移更新。
- write pos 和 checkpoint 之间的还空着的部分可以用来写入新的 redo log 记录。
为何不直接把数据写入磁盘,而是先把redo log写入磁盘?
1、数据大小不同:如果是写 redo log,一行记录可能就占几十 Byte,只包含表空间号、数据页号、磁盘文件偏移量、更新值。而如果是写数据,数据页大小是16KB,可能就修改了数据页里的几 Byte 数据。
2、写入方式不同:redo log写入方式是顺序写入,而数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能是很差。
undo log
1. 定义与作用
Undo Log(回滚日志)是InnoDB存储引擎中的一种逻辑日志,主要用于实现事务的原子性和隔离性。它记录了事务在修改数据前的原始状态,以便在事务回滚或数据库崩溃时能够恢复数据到原始状态。此外,Undo Log还用于实现多版本并发控制(MVCC),帮助实现隔离性。
2. 主要功能
- 事务回滚:当事务在执行过程中出现错误或用户主动回滚时,Undo Log记录了每次数据修改前的状态。通过Undo Log,数据库可以将数据恢复到修改前的状态,从而实现事务的原子性。
- 多版本并发控制(MVCC):为了支持一致性读(snapshot read),当一个事务启动后,即使其他事务修改了数据,当前事务依然可以通过Undo Log看到修改前的数据版本,从而构建出一个一致的快照视图。
3. 工作原理
- 记录旧值:在执行数据更新操作之前,InnoDB会先将即将被修改的数据的旧值写入Undo Log。这样,当事务需要回滚时,系统就可以利用这些旧值撤销修改,确保数据回到原始状态。
- 版本链:每次更新记录时,旧值被复制到Undo Log中,形成版本链,支持多版本并发控制(MVCC)。
4. 存储与管理
- 存储位置:Undo Log存储在InnoDB的表空间中,通常位于
ibdata1
文件或独立的undo表空间中。从MySQL 8.0版本开始,默认会创建两个独立的undo表空间文件,文件名通常为undo_001
和undo_002
。 - 回滚段(Rollback Segment):InnoDB通过Rollback Segment来管理Undo Log文件,每个事务会使用一个Undo Log Segment。
- Undo Log Segment(slot):最小存储单元,每个slot对应一个事务的Undo Log记录。事务开始时,需要为其分配一个rollback segment。
5. 使用场景
- 事务回滚:当事务执行过程中出现错误或用户主动回滚时,通过Undo Log恢复数据到事务开始前的状态。
- MVCC:支持一致性读,允许多个事务同时读取数据而不会相互干扰。通过Undo Log中的历史版本数据,实现多版本并发控制。
6.补充
redo log 与undo log
在MySQL的InnoDB存储引擎中,Undo Log和Redo Log是两种重要的日志类型,它们在功能、作用和实现方式上存在一些区别:
特性 | Undo Log | Redo Log |
---|---|---|
定义 | 逻辑日志,记录事务对数据的修改前的原始值 | 物理日志,记录数据页的物理修改操作 |
作用 | 实现事务的原子性和隔离性(MVCC),支持事务回滚 | 实现数据的持久性和崩溃恢复 |
存储位置 | InnoDB的表空间中,通常在独立的undo表空间 | InnoDB的表空间中,通常在redo log文件组 |
写入时机 | 事务执行过程中,每修改一条数据时写入 | 事务执行过程中,数据页修改时写入缓冲区,根据策略刷盘 |
内容类型 | 逻辑记录,包含修改前的数据值 | 物理记录,包含数据页的物理修改信息 |
生命周期 | 事务提交后,部分undo log可清理 | 持续存在,用于数据库崩溃恢复 |
与事务的关系 | 用于事务回滚和MVCC | 用于保证事务提交后的数据持久性 |
刷盘策略 | 通常与redo log配合,依赖redo log的刷盘 | 受innodb_flush_log_at_trx_commit 等参数控制 |
详细解释
-
定义与内容:
- Undo Log:属于逻辑日志,记录的是事务对数据进行修改前的原始值,用于在事务回滚时恢复数据到修改前的状态。例如,当执行一条
UPDATE
语句时,Undo Log会记录该语句修改前的旧值。 - Redo Log:属于物理日志,记录的是数据页的物理修改操作,如在某个数据页的某个位置修改了什么值。它不关心数据的逻辑意义,只关注数据页的实际变化。
- Undo Log:属于逻辑日志,记录的是事务对数据进行修改前的原始值,用于在事务回滚时恢复数据到修改前的状态。例如,当执行一条
-
作用与功能:
- Undo Log:主要用于实现事务的原子性和隔离性。通过记录修改前的数据,Undo Log可以在事务失败或回滚时恢复数据。同时,Undo Log支持多版本并发控制(MVCC),使得不同事务可以看到数据的不同版本。
- Redo Log:主要用于实现数据的持久性和崩溃恢复。当系统崩溃后,InnoDB可以通过Redo Log重新做(redo)数据页的修改操作,将数据恢复到崩溃前的状态。
-
存储位置与写入时机:
- Undo Log:存储在InnoDB的表空间中,通常位于独立的undo表空间。在事务执行过程中,每修改一条数据时写入。
- Redo Log:存储在InnoDB的redo log文件组中。在事务执行过程中,数据页修改时写入缓冲区,根据刷盘策略(如事务提交、定时等)刷盘。
-
生命周期与刷盘策略:
- Undo Log:事务提交后,部分undo log可以被清理。其生命周期与事务相关,主要用于事务回滚和MVCC。
- Redo Log:持续存在,用于数据库崩溃恢复。其刷盘策略受参数
innodb_flush_log_at_trx_commit
等控制,确保数据的持久性。
总结
Undo Log和Redo Log在InnoDB存储引擎中扮演着不同的角色,共同协作以确保数据的完整性和一致性。Undo Log侧重于事务的原子性和隔离性,通过记录修改前的数据实现事务回滚和MVCC;Redo Log侧重于数据的持久性和崩溃恢复,通过记录数据页的物理修改操作实现数据的持久化。两者相辅相成,共同维护数据库的稳定性与可靠性。
Binlog(二进制日志)
1. 定义与作用
Binlog(二进制日志)是MySQL Server层的一种日志,用于记录所有对数据库进行的修改操作(如插入、更新、删除等)。它的主要作用包括数据备份和恢复、主从复制等。
2. 记录内容
Binlog记录的是逻辑操作,而不是物理存储层面的修改。例如,它会记录一条INSERT
语句,而不是具体的数据页修改。
3. 日志格式
Binlog有三种格式,可以通过binlog_format
参数指定:
-
Statement格式:记录的是SQL语句原文,如
UPDATE T SET c=1 WHERE id=2
。这种格式的优点是占用空间小,但可能因SQL语句的非确定性导致主从数据不一致。
-
Row格式:记录的是数据行的更改,即具体修改了哪些行、修改前后的值。这种格式保证了数据一致性,但占用空间较大。
-
Mixed格式:混合了Statement和Row两种格式,MySQL会根据语句是否可能导致数据不一致来选择使用哪种格式。
4. 写入机制
- 事务提交时写入:Binlog只在事务提交时写入,确保只有已提交的事务才会被记录。
- 顺序写入:Binlog是顺序写入的,每个事务的Binlog不能被拆分,系统会为每个线程分配一个内存块作为Binlog缓存。
- 上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快
- 上图的 fsync,才是将数据持久化到磁盘的操作
5. 配置参数
- binlog_format:设置Binlog的格式,可选值为
STATEMENT
、ROW
、MIXED
。 - sync_binlog:控制Binlog的刷盘策略。默认值为1,表示每次提交事务都会执行
fsync
操作,将Binlog从缓存写入磁盘。设置为0时,性能更高,但安全性较低。
6. 使用场景
- 数据备份与恢复:通过定期备份Binlog,可以实现数据库的增量备份。在数据恢复时,可以重放Binlog中的操作,将数据库恢复到某个时间点的状态。
- 主从复制:在主从复制架构中,主服务器将Binlog发送给从服务器,从服务器通过重放这些日志来同步数据,保持数据一致性。
总结
在MySQL的InnoDB存储引擎中,Redo Log、Undo Log和Binlog是三种非常重要的日志,它们在数据库的运行和数据管理中发挥着不同的作用,共同维护着数据库的稳定性与可靠性。以下是对这三种日志的总结:
特性 | Redo Log | Undo Log | Binlog |
---|---|---|---|
定义 | 物理日志,记录数据页的物理修改操作 | 逻辑日志,记录事务对数据的修改前的原始值 | 逻辑日志,记录所有对数据库进行的修改操作 |
作用 | 实现数据的持久性和崩溃恢复 | 实现事务的原子性和隔离性(MVCC),支持事务回滚 | 数据备份和恢复、主从复制等 |
存储位置 | InnoDB的表空间中,通常在redo log文件组 | InnoDB的表空间中,通常在独立的undo表空间 | MySQL的数据目录下,文件名通常为binlog.000001 等 |
写入时机 | 事务执行过程中,数据页修改时写入缓冲区,根据策略刷盘 | 事务执行过程中,每修改一条数据时写入 | 事务提交时写入 |
内容类型 | 物理记录,包含数据页的物理修改信息 | 逻辑记录,包含修改前的数据值 | 逻辑操作,记录的是SQL语句的逻辑操作 |
生命周期 | 持续存在,用于数据库崩溃恢复 | 事务提交后,部分undo log可清理 | 持续存在,用于数据备份和恢复 |
与事务的关系 | 用于保证事务提交后的数据持久性 | 用于事务回滚和MVCC | 用于数据的备份和恢复 |
刷盘策略 | 受innodb_flush_log_at_trx_commit 等参数控制 | 通常与redo log配合,依赖redo log的刷盘 | 受sync_binlog 等参数控制 |
详细解释
-
Redo Log(重做日志):
- 物理日志:记录的是数据页的物理修改操作,如在某个数据页的某个位置修改了什么值。
- 持久性和崩溃恢复:当系统崩溃后,InnoDB可以通过Redo Log重新做(redo)数据页的修改操作,将数据恢复到崩溃前的状态。
- 写入时机:在事务执行过程中,数据页修改时写入缓冲区,根据刷盘策略(如事务提交、定时等)刷盘。
-
Undo Log(回滚日志):
- 逻辑日志:记录的是事务对数据进行修改前的原始值,用于在事务回滚时恢复数据到修改前的状态。
- 原子性和隔离性:通过记录修改前的数据,Undo Log可以在事务失败或回滚时恢复数据。同时,Undo Log支持多版本并发控制(MVCC),使得不同事务可以看到数据的不同版本。
- 写入时机:在事务执行过程中,每修改一条数据时写入。
-
Binlog(二进制日志):
- 逻辑日志:记录的是所有对数据库进行的修改操作,如插入、更新、删除等。
- 数据备份与恢复、主从复制:通过定期备份Binlog,可以实现数据库的增量备份。在数据恢复时,可以重放Binlog中的操作,将数据库恢复到某个时间点的状态。在主从复制架构中,主服务器将Binlog发送给从服务器,从服务器通过重放这些日志来同步数据,保持数据一致性。
- 写入时机:在事务提交时写入。