在我的理解中,mysql binlog 完全可以作为 InnoDB 的重做日志。

那么,启用binlog后,为什么InnoDB还要同时写redo log而不是直接切换使用binlog呢?这不会显着降低数据库写入性能吗?

除了简化设计和实现之外,这样做还有什么好处吗?

AFAIK,在保证ACID合规性的情况下同时启用两个日志,会出现以下问题:

  • 每个具有相同含义的日志记录必须分别写入两次。
  • 每次事务或事务组提交时刷新两个日志。
  • 为了保证两个日志文件之间的一致性,使用了复杂且低效的方式,例如XA(2PC)。

  • 因此,所有其他产品似乎都只使用一组日志(SQL Server 称为事务日志,ORACLE 称为重做日志,PostgreSQL 称为 WAL)来完成所有相关工作。难道只有 MySQL 必须同时打开两组日志才能保证 ACID 合规性和强一致的主从复制?

    有没有一种方法可以实现 ACID 合规性和强一致性半同步复制,而只启用其中一个?

    请您参考如下方法:

    这是一个有趣的话题。长期以来,我一直在倡导合并InnoDB write-ahead log和binlog的想法。这样做的最大动机是不再需要同步两个单独的日志。但是,我担心这可能不会很快发生。

    在 MariaDB,我们正在采取一些措施来减少 fsync() 开销。 MDEV-18959 Engine transaction recovery through persistent binlog的想法是为了保证 binlog 永远不会落后于 InnoDB 重做日志,从而允许在 binlog 文件上仅通过一次 fsync() 调用进行持久的、崩溃安全的事务提交。

    binlog 实现逻辑日志记录,而 InnoDB 重做日志实现物理日志记录(涵盖对实现撤消日志和索引树的持久数据页的更改)。正如我在 M|18 Deep Dive: InnoDB Transactions and Write Paths 中解释的那样,一个用户事务被分成多个小事务,每个小事务可以原子地修改多个数据页。

    重做日志是对多个数据页进行原子更改的“粘合剂”。我认为重做日志对于实现就地更新数据结构的原子更改是绝对必要的。仅追加数据文件结构(例如 LSM 树)本身可以是日志,不一定需要单独的日志。

    对于包含二级索引的 InnoDB 表,每个单行操作实际上都被分成多个小事务,分别对每个索引进行操作。因此,事务层需要更多的“胶水”来使表的索引彼此一致。这种“胶水”由撤消日志提供,它在持久数据页中实现。

    InnoDB 预先对索引页执行更改,提交是一个快速操作,仅更改撤消日志 header 中事务的状态。但是回滚非常昂贵,因为撤消日志必须向后重播(并且将写入更多重做日志以覆盖那些索引页更改)。

    在 MariaDB Server 中,MyRocks 是另一个事务性存储引擎,它的作用正好相反:缓冲内存中的更改直到最后,并在提交时将它们应用到数据文件。这使得回滚非常便宜,但事务的大小受可用内存量的限制。我了解 MyRocks 可以按照您建议的方式工作。


    评论关闭
    IT序号网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!