MySQL中的几种主要日志

187 阅读9分钟

背景

之前整理过MySQL中的各种锁,这次整理下它的各种日志,不是全部的类型的日志,这次整理的是 binlog , redolog, undolog这三种类型

Binlog

最早听到binlog是在多个数据源中同步数据的设计方案中,大概的意思是,通过监听binlog实现不同的数据源同步数据的目的,那么它到底有哪些作用呢?

Binlog的作用

  • 复制: 在主从复制中,Binlog用于在Master和Slave之间传递数据变化,以保持数据一致性。
  • 数据恢复: 可以通过mysqlbinlog工具来恢复数据
  • 数据回放: 增量备份

什么是Binlog呢

Binlog是MySQL Server层的重要日志之一,用于记录所有改变了数据的语句和事件。这包括INSERT、UPDATE、DELETE等操作,同时也可以记录事务的开始和提交

写入过程

在事务执行的过程中写入缓冲区,在事务提交的时通过配置参数选择是否及时落盘, 这个参数是sync_binlog一共有三种情况, 0;1;>1;

  • sync_binlog = 0: 表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失
  • sync_binlog = 1: 每次事务提交时,Binlog都被同步持久化到磁盘。这确保了即使系统崩溃也不会丢失已提交事务的日志,但影响性能
  • sync_binlog > 1: inlog日志可能会在多个事务提交后才被刷盘。这减少频繁的磁盘I/O,提升性能,但在崩溃时存在数据丢失风险。 在8.0版本之前的sync_binlog的默认值是0,在8.0版本后sync_binlog的默认值是 1

记录格式

  • Statement: 记录每一条会导致数据变化的SQL语句
  • Row: 记录每一行的具体更改,很详细,但体积会很大
  • Mixed: 结合了Statement和Row两者的优点,根据需要选择最优的记录方式

主从复制过程:

image.png

  • 记录binlog: 主数据库上,当一个事务提交时,所有的数据修改(INSERT、UPDATE、DELETE等)都会被记录到二进制日志(Binlog)中
  • 请求同步: 从数据库上有一个I/O线程,它负责与主数据库建立连接并请求新的Binlog。
  • 同步Binlog: 主数据库的Binlog传输给从服务器的I/O线程,该线程将这些日志写入从数据库的中继日志(Relay Log)中
  • 从数据库回放: 从数据库有一个SQL线程,它负责读取中继日志的内容然后执行与主服务器上相同的更改。这使得从数据库与主数据库保持同步。

RedoLog

RedoLog的作用

  • 权衡性能和安全: 当有数据变化时,如果我们每一次都去更新磁盘,那么效率会很低,因为数据的更改会伴随着磁盘的随机访问.但如果不去更新磁盘安全性就无法得到保证,比如出现了断电,内存中的更改都将消失.而relog很好的解决了这个问题, 将修改先放到redolog的缓存中,在适当的时机(事务提交和定时)刷新到磁盘上,因为日志的写入是顺序写的,这就避免了磁盘的随机访问,提高了写入效率,一旦redolog写入了,那么即便是数据库重启,或是断电等数据都不会丢失
  • 数据恢复: 当数据库因为硬件故障、软件错误或者人为误操作等原因陷入困境时,RedoLog 就是那根 “救命稻草”。比如,数据库服务器突然断电重启,MongoDB 启动恢复流程时,就会读取 RedoLog,按照里面记录的操作顺序,一步步重演那些未完成的事务,让数据库重回正轨,数据状态恢复到故障前的一致性,最大程度减少损失。

写入时机

  • 事务提交时: 当一个事务提交时,InnoDB 会将该事务的所有变更记录写入 redo log,并确保已经将这些变化刷新到磁盘。
  • Log Buffer满时: redo log 变更首先写入内存中的 log buffer,InnoDB 会定期将 log buffer 中的数据刷新到磁盘上的 redo log。默认情况下,当 log buffer 使用的空间达到 1 MB 时,InnoDB 会自动触发刷新操作。
  • 后台刷新: innoDB 的后台线程会定期将 log buffer 中的数据刷新到磁盘上。这个操作是异步的,通常会在后台不断地发生。具体是由参数 innodb_flush_log_at_trx_commit控制

innodb_flush_log_at_trx_commit

innodb_flush_log_at_trx_commit参数控制刷盘间隔,有下面几种情况:

  • 0: 每一秒刷数据到磁盘,性能高,但可能会丢失一秒钟的数据
  • 1: 事务提交时,系统将会redolog日志写入磁盘(同步刷新),这也是默认设置,保证了数据的安全性,只要提交成功的事务比如是能恢复数据的
  • 2: 每次事务提交时,日志缓冲区会被写入操作系统缓存(Page Cache),但物理上磁盘写操作由后台线程完成。

两阶段提交

两阶段提交为了解决什么问题
  • MySQL 的存储引擎与日志机制:MySQL 的 InnoDB 存储引擎使用 redolog 来保证事务的持久性,在事务进行过程中,会先将数据的修改记录在 redolog 中,然后再将实际的数据页进行更新。而 MySQL 的 Server 层使用 binlog 来进行数据的备份和主从复制等操作,binlog 是在事务提交时一次性写入的。
  • 故障恢复场景下的不一致风险:在数据库运行过程中,可能会出现各种故障,如服务器突然宕机、进程异常退出等。如果在事务提交过程中,先写入了 binlog,然后在写入 redolog 之前发生故障,那么在故障恢复时,由于 redolog 中没有该事务的完整记录,就会导致该事务对数据的修改无法恢复,从而造成数据不一致。相反,如果先写入 redolog,后写入 binlog,在故障恢复后,虽然数据在本地已经修改,但由于 binlog 未记录,可能会导致从库与主库数据不一致。
具体执行过程
  • 阶段一:准备阶段(Prepare)

    • 事务开始执行,InnoDB 存储引擎会将事务的修改操作记录到 redolog 中,并将 redolog 的状态设置为 “prepare”,表示事务已经准备好提交,但尚未真正提交。
    • 同时,将事务的执行结果返回给 MySQL 的 Server 层。
  • 阶段二:提交阶段(Commit)

    • 如果在阶段一中,事务在存储引擎层执行成功,MySQL 的 Server 层收到存储引擎层返回的 “prepare” 成功的消息后,会将事务的操作记录到 binlog 中。
    • 然后,MySQL 的 Server 层向 InnoDB 存储引擎发送提交事务的指令,InnoDB 存储引擎收到指令后,将 redolog 的状态从 “prepare” 设置为 “commit”,表示事务已经提交成功,同时将事务在内存中的数据页更新到磁盘上,完成事务的最终提交。

image.png

binlog和redolog是否重复

为什么不能使用binlog来恢复数据,而要使用redolog来恢复数据呢

  • 粒度和效率问题:
    • Redo log 在物理层面记录变更,因此在崩溃后恢复时可以更直接和有效。相对而言,binlog 还原需要 SQL 解析和执行,粒度较粗,恢复效率不及 redo log。
  • 持久性保障机制:
    • 使用 redo log,事务在提交时即可保证数据的持久性,通过原子写入和崩溃恢复机制确保数据一致性。而 binlog 主要用于复杂的事务性追踪和跨服务器的数据同步 尽管 binlog 在复制和备份中发挥着重要作用,但当涉及到高效快速的崩溃恢复时,redo log 是更为合适和高效的选择。为了实现高效的运行和可靠性,MySQL 采用了 Relay Log 和 Binlog 为复制和备份服务,而依靠 redo log 实现快速恢复。

Undolog

当数据变化时,记录反向操作的SQL,比如INSERT操作就记录一条DELETE; 比如DELETE操作就记录一条INSERT;一个事务把A从5变成10,那么反向的记录就是从10会到5

Undolog的作用

  • 事务的回滚: 这个就不用多说了,反向记录让回滚很容易
  • 是MVCC的基础: MVCC 允许不同事务在同一时间看到数据的不同版本,而 UndoLog 就是维护这些版本数据的关键。每一次数据更新,除了为当前事务生成新的数据版本,还会通过 UndoLog 关联起旧版本,构建起一条完整的数据版本链。这样,不同事务就能依据自身的可见性规则,沿着这条链找到合适的版本进行读取,既提高了并发性能,又靠 UndoLog 保障了数据一致性。

UndoLog的写入流程

  • 生成反向操作记录: 当事务中的数据修改指令下达,数据库引擎首先解析这个操作,然后根据操作类型和涉及的数据,精心构造出与之对应的反向操作。例如,对于插入操作,反向操作就是删除刚插入的记录;对于更新操作,反向操作就是将更新后的值还原回原值。这个生成过程迅速且精准,确保 UndoLog 记录的有效性。
  • 写入缓冲区: 和 RedoLog 类似,UndoLog 也有自己的内存缓冲区。生成的反向操作记录首先被快速写入这个缓冲区,它就像一个临时的 “撤销操作仓库”,利用内存的高速读写特性,快速收纳大量的反向操作记录,避免频繁直接操作磁盘带来的性能瓶颈。多个事务的 UndoLog 条目在这里有序排列,等待后续处理。
  • 持久化: 一方面,为了保证 UndoLog 的可靠性,防止系统故障导致数据丢失而无法回滚事务,数据库会有后台线程定期将缓冲区中的 UndoLog 刷盘到磁盘上的日志文件。另一方面,当事务提交或回滚时,相关的 UndoLog 也会即时触发刷盘操作。刷盘过程遵循严格的顺序,确保与事务执行顺序一致,这样在需要利用 UndoLog 恢复数据时,才能按照正确的历史轨迹回溯,保障数据一致性。

总结

MySQL中的三种日志,简单理解这三种日志:

  • binlog主要用于数据之间的同步,例如主从复制,多数据源的数据同步
  • redolog用于数据库的恢复,是保证数据持久性的
  • undolog用于回滚事务,也是mvcc的基础