启用mysql binlog后,为什么仍需要innodb重做日志?

ASB*_*Bai 0 mysql innodb transactions acid mariadb

以我的理解,mysql binlog可以完全充当InnoDB的重做日志。

那么,启用Binlog后,为什么InnoDB必须同时编写重做日志,而不是仅仅切换为使用Binlog?这是否会大大降低数据库的写入性能?

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

AFAIK,要在保证ACID符合性的同时启用两个日志,将发生以下问题:

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

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

在仅启用其中一项的情况下,是否有一种方法可以实现ACID遵从性和强大的一致半同步复制?

Mar*_*elä 5

这是一个有趣的话题。很长一段时间以来,我一直提倡合并InnoDB预写日志和binlog的想法。这样做的最大动机是不需要同步两个单独的日志。但是,恐怕这可能不会很快发生。

在MariaDB,我们正在采取一些措施来减少fsync()的开销。通过持久性二进制日志进行MDEV-18959引擎事务恢复的想法是,确保二进制日志永远不会落后于InnoDB重做日志,从而允许仅通过一个fsync()调用就可以进行持久,崩溃安全的事务提交。 binlog文件。

Binlog实现逻辑日志记录时,InnoDB重做日志实现物理日志记录(覆盖对实现撤消日志和索引树的持久数据页的更改)。正如我在M | 18 Deep Dive:InnoDB事务和写入路径中所解释的那样,用户事务被划分为多个小型事务,每个事务都可以原子地修改多个数据页。

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

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

InnoDB预先对索引页进行更改,并且提交是一项快速操作,仅更改撤消日志标头中的事务状态。但是回滚非常昂贵,因为撤消日志将不得不向后重放(并且将写入更多的重做日志来覆盖那些索引页的更改)。

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

  • @ASBai 你是对的。多年来我一直提倡将所有日志事件写入单个文件的想法。在 https://jira.mariadb.org/browse/MDEV-12353 中,我正在研究一种新的 InnoDB 重做日志格式,该格式允许添加“外部”日志事件。用于解析和应用日志的更简单的代码也可以更轻松地实现物理复制(无需 binlog)。 (2认同)