undo log 和 binlog

本文最后更新于:2021年11月2日 晚上

基本概念

  • 数据库中数据存放的文件称为data file,日志文件称为log file

  • 数据库中数据都是有缓存的,如果没有缓存,每次都得读或者写磁盘,性能非常差劲;

    • 数据的缓存称为data buffer,日志的缓存称为log buffer
  • 内存缓冲池 buffer pool

    • buffer pool是 物理页 的缓存,对 InnoDB 的任何修改操作都会首先在 bp 的 page 上进行,然后这样的页面将被标记为 dirty 并被放到专门的flush list 上,后续将由专门的刷脏线程阶段性的将这些页面写入磁盘
    • 这样的好处是避免每次写操作都操作磁盘导致大量的随机 IO,阶段性的刷脏可以将多次对页面的修改 merge 成一次IO 操作,同时异步写入也降低了访问的时延。
    • 然而,如果在 dirty page 还未刷入磁盘时,server非正常关闭,这些修改操作将会丢失,如果写入操作正在进行,甚至会由于损坏数据文件导致数据库不可用。为了避免上述问题的发生,Innodb 将所有对页面的修改操作写入一个专门的文件,并在数据库启动时从此文件进行恢复操作,这个文件就是 redo log file。这样的技术推迟了 bp 页面的刷新,从而提升了数据库的吞吐,有效的降低了访问时延。带来的问题是额外的写 redo log 操作的开销(顺序 IO,比随机 IO 快很多),以及数据库启动时恢复操作所需的时间。

redo/undo log

  • redo log是物理日志,记录物理页的修改,用来恢复已经commit的数据,保持持久性数据库启动时,再做一遍,以恢复数据状态
  • undo log用来回滚记录到某个版本,保证事务的原子性撤销某些操作,以恢复数据状态
    • 在innodb引擎中,MVCC的实现也借助于undo log

在系统恢复时,

  • 通过redo log恢复所有已经在存储引擎内部commit的事务;

  • 而有些事务还未提交,但数据已被修改过了,即redo log处于prepare状态,但没有commit,为保证原子性,需借助undo log进行回滚。

为什么只用redo log 或者 undo log不行?

  • 只有undo log,没有redo log:如果脏数据尚未刷入磁盘,服务器宕机了,会丢失保存在缓存中的已经提交的数据,无法保证持久性。必须保证在提交事务前完成刷脏,但这样会损害性能。(一般在空闲时刷脏,实时刷脏io开销较大)
  • 只有redo log,没有undo log:无法随心所欲地在事务提交前刷脏,即:如果刷脏完成后尚未commit时,服务器崩了;redo log未commit,需要回滚数据,但这部分数据是无法完成回滚的

redo/undo log 和bin log

  • 层次不同:redo/undo log是innodb引擎层的日志,而binlog是server层的日志,所有引擎共享binlog
  • 记录内容不同:redo/undo log 记录的是每个数据页的修改情况,binlog的Statement格式下记录 SQL语句、Row格式记录每一行改动情况、Mixed格式混合记录;
  • 记录时机不同:redo/undo log在事务执行过程中记录,而binlog在事务最终提交前写入;binlog 什么时候刷新到磁盘和参数sync_binlog有关

参考文件


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!