我试图了解percona如何进行热备份的过程。据了解,他们使用innodb崩溃恢复机制并执行以下步骤。
- 存储/记住重做日志中的起始LSN
- 复制数据文件
- 执行 LOCK BINLOG FOR BACKUP:阻止可能更改二进制日志位置的所有操作
- 复制 REDO 日志文件并获取二进制日志坐标
- 完成的xtrabackup将解锁二进制日志和表。
我想从重做日志中了解LSN的作用是什么,我们不能直接检查步骤1中的二进制日志位置吗?
那么最终的LSN呢,它在流程中的任何地方都没有使用吗?
我试图了解percona如何进行热备份的过程。据了解,他们使用innodb崩溃恢复机制并执行以下步骤。
我想从重做日志中了解LSN的作用是什么,我们不能直接检查步骤1中的二进制日志位置吗?
那么最终的LSN呢,它在流程中的任何地方都没有使用吗?
LSN(日志序列号)类似于二进制日志位置,但重做日志是不同的日志。它仅适用于 InnoDB 页面,并且包含受影响页面的物理差异。在崩溃恢复期间,它可以通过将差异应用于原始页面来重建页面。它还可以检测是否已将更改应用到页面,因为页面带有 LSN 标记。它处理崩溃前刷新的页面的情况,这些页面不一定以任何顺序发生。因此,从较早的 LSN 开始,不需要应用重做日志中的每个更改。
二进制日志适用于任何存储引擎的表,它包含逻辑变化。它可能包含基于行的事件或基于语句的事件。它不用于崩溃恢复。二进制日志是严格排序的,因此如果您使用它来同步数据库(例如复制或时间点恢复),则它假定所有更改都将从您指定的起始位置应用。
Percona XtraBackup 不需要记录最后一个 LSN,因为崩溃恢复只是处理所有重做日志直到最后。
不,那是不正确的。请记住,事务对修改的行数或更改的数量没有限制。因此,必须以某种方式对更改进行排队,以允许事务的大小较大。
对于二进制日志,更改将写入二进制日志缓存。每个会话都分配有自己的二进制日志缓存。默认情况下这是在内存中的,但是如果事务大于内存中的缓存,则可以将其复制到磁盘。当您执行 INSERT/UPDATE/DELETE 时,这些更改将附加到相应会话的二进制日志缓存中。
在 COMMIT 上,所有更改最终都会从会话的二进制日志缓存复制到二进制日志。因此,在 COMMIT 之前,更改不会出现在二进制日志中。
重做日志是独立的,这仅在InnoDB存储引擎中实现。当执行INSERT/UPDATE/DELETE时,缓冲池中的数据页被修改。此时,这些未提交的页面更改也会写入重做日志中。由于重做日志具有固定大小,因此您可能会进行太多更改以适应重做日志,并且它会回绕到开头。为了防止在崩溃时丢失更改,必须在重做日志回绕之前将缓冲池中的修改页刷新到磁盘。
在 COMMIT 上,InnoDB 不需要复制任何日志或刷新任何修改的页面。页面可能会在缓冲池中保持修改状态。通过将一条小记录写入重做日志,仅将事务标记为已提交。因此,如果需要崩溃恢复,它就知道哪些页面包含已提交的更改。崩溃时未提交的页面标记有事务 ID,该事务 ID 未在重做日志中记录为已提交,因此不需要恢复这些页面。
重做日志会连续写入,就像执行 INSERT/UPDATE/DELETE 一样,并且会在 COMMIT 期间写入,以将每个事务标记为已提交。但除非在崩溃恢复期间,否则不会读取重做日志。它的唯一目的是重建缓冲池中修改的页面。
LSN 的使用使得崩溃恢复知道从哪里开始处理重做日志。例如,如果大多数修改的页面在崩溃时已被刷新,则无需在缓冲池中仍被修改的最旧页面之前处理重做日志。崩溃恢复可以直接跳到重做日志中最旧的修改页对应的LSN。这有助于崩溃恢复运行得更快一些。
Percona XtraBackup 使用相同的重做日志处理代码,因为准备备份类似于崩溃恢复。当 Percona XtraBackup 开始复制备份页面时,其中一些页面可能已修改缓冲池中的副本。复制需要一段时间,并且随着后续查询流量执行 INSERT/UPDATE/DELETE,某些页面可能会在这段时间内被刷新或被修改。当 XtraBackup 准备运行时,它必须检查所有重做日志,直到备份开始时对应于 LSN 的最旧修改页面,因为其中任何一个都可能是“丢失”页面,即仅来自磁盘的页面已复制到备份,缓冲池中没有修改版本。
修改的页面会不断刷新到表空间。阅读https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool-flushing.html
希望刷新修改页面的速度至少足够快,以使重做日志不会达到 100% 满。InnoDB 不允许未刷新的修改页存在于缓冲池中,如果它们在崩溃时无法由重做日志恢复。
如果重做日志达到 100% 已满,则对重做日志的写入必须暂停,直到某些页面刷新可以跟上。这意味着所有 INSERT/UPDATE/DELETE 操作都将暂时被阻止。您必须使 MySQL 实例严重超载才能达到此状态(即以高于其所能承受的写入速率加载它)。