更多博客请见 我的语雀知识库

什么是三大日志

  • **bin日志: **保存的是当前数据库中最新的数据以及表结构变更的语句,不包含每行数据的历史版本。
  • undo日志:不仅保存了最新的数据,也保存了每行数据的历史版本,为事务回滚和MVCC提供了支持。
  • redo日志:保存内存缓冲区BufferPool中脏页的数据,不保存已经被刷到磁盘中的数据,也就是说,redo日志保存的数据是不全的。redo日志只是为了应对因为断电等原因BufferPool还没来得及刷到磁盘就丢失了的情况。redo日志默认每秒钟都会刷一次盘,事务提交时也会刷盘,mysql关闭时也会刷盘。

总结

redo的作用是对Bufferpool中脏页的持久化。保存的是脏页更新后的值。 而undo保存的更新前的值。对undo的刷盘是异步的,不知道它什么时候刷。万一刷盘过程中宕机,bufferpool脏页的数据就全没了。为了不让它全没,就有了redo对Bufferpool的持久化。

问题

三个log的记录顺序是什么?

  • undo:在事务开启时就会记录数据;
  • redo: 在增删改语句执行之前就会记录数据;
  • bin: 在增删改语句执行之后会生成一条binlog。事务提交时这条binlog会写入磁盘的binlog。
    一个log文件写满之后,会创建一个新的log文件接着写入。

为什么有了 binlog, 还要有 redo log?

这个问题跟 MySQL 的时间线有关系。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。 而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用 redo log 来实现 crash-safe 能力。

有了undolog为啥还需要redolog呢,不能直接undolog+最新数据刷盘吗

最新数据也就是BufferPool里面的内存数据,当增删改的sql执行成功后,一些缓存页就会被修改,这些被修改的数据以脏页的形式存放在BufferPool中。 一旦服务器宕机,这些脏页的数据就全没了。 所以要保证脏页的数据在宕机之间就被持久化。而这就靠redolog保证了。 为了防止断电导致数据丢失的问题,当有一条记录需要更新的时候,InnoDB 引擎就会更新内存(同时标记为脏页),然后将本次对这个页的修改以 redo log 的形式记录下来。 当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化。根据redo就可以恢复完整的原内存数据了。

为什么要增加一个redolog来保证BufferPool脏页的持久化?直接把脏页持久化到磁盘不行吗?redolog也是持久化到磁盘啊?

直接持久化Buffer Pool的局限性

  1. 性能影响:脏页的数据在B+树中存储的位置基本不是连续的,必然会有大量的随机IO。
  2. 并发问题:直接将Buffer Pool的内容写回磁盘会导致更多的锁竞争,因为多个事务可能同时尝试写入相同的页面。
  3. 数据完整性风险:如果在事务提交过程中发生崩溃,而修改尚未完全写入磁盘,那么数据可能处于不一致状态。

    redoLog的改善

  4. 性能影响:redo的写入是顺序的,是磁盘顺序io,比随机io快得多
  5. 并发问题:redo是由后台单线程管理的,天然避免了并发问题。
  6. 数据完整性风险:InnoDB维护一个叫做Checkpoint的机制,它记录了最后成功完成的Redo Log的位置。在系统重启时,InnoDB可以从这个位置开始重做,以确保所有已完成的事务都被正确处理

本问题的回答由AI生成 https://lxblog.com/qianwen/share?shareId=cf89a692-e026-4745-a132-fe6afc901f2b