Skip to main content

2.处理副本意外停止

为了使复制能够适应服务器的意外停止(有时称为崩溃安全),副本必须能够在停止之前恢复其状态。 本节介绍复制期间副本意外停止的影响,以及如何配置副本以获得最佳恢复机会以继续复制。

副本意外停止后,重新启动时复制 SQL 线程必须恢复有关已执行哪些事务的信息。 恢复所需的信息存储在副本的应用程序元数据存储库中。 该存储库默认创建为名为 mysql.slave_relay_log_info 的 InnoDB 表。 通过使用此事务存储引擎,信息在重新启动时始终可恢复。 对应用程序元数据存储库的更新与事务一起提交,这意味着该存储库中记录的副本进度信息始终与已应用于数据库的信息一致,即使在服务器意外停止的情况下也是如此。

DML 事务和原子 DDL 更新 mysql.slave_relay_log_info 表中副本应用程序元数据存储库中的复制位置,并将更改应用到数据库,作为原子操作。 在所有其他情况下,包括不完全原子的 DDL 语句和不支持原子 DDL 的豁免存储引擎,如果服务器意外停止,mysql.slave_relay_log_info 表可能会丢失与复制数据关联的更新。 在这种情况下恢复更新是一个手动过程。

副本从意外停止中恢复的恢复过程因副本的配置而异。 恢复过程的细节受到所选择的复制方法、副本是单线程还是多线程以及相关系统变量的设置的影响。 恢复过程的总体目标是确定在意外停止发生之前已在副本数据库上应用了哪些事务,并检索和应用意外停止后副本丢失的事务。

  • 对于基于 GTID 的复制,恢复过程需要副本已接收或提交的事务的 GTID。 可以使用 GTID 自动定位从源检索丢失的事务,GTID 自动定位会自动将源的事务与副本的事务进行比较并识别丢失的事务。
  • 对于基于文件位置的复制,恢复过程需要准确的复制 SQL 线程(应用程序)位置,显示应用于副本的最后一个事务。 基于该位置,复制 I/O 线程(接收器)从源的二进制日志中检索从该点开始应应用于副本的所有事务。

使用基于 GTID 的复制可以最轻松地配置复制以适应意外停止。 GTID 自动定位意味着副本可以可靠地识别和检索丢失的事务,即使应用的事务序列中存在间隙。

以下信息提供了适用于不同类型副本的设置组合,以保证在复制控制下的恢复。

注意:

复制控制之外的一些因素可能会影响复制恢复过程以及恢复过程后复制的整体状态。 特别是,影响各个存储引擎恢复过程的设置可能会导致事务在副本意外停止时丢失,从而无法用于复制恢复过程。 下面列表中提到的 innodb_flush_log_at_trx_commit=1 设置是使用 InnoDB 和事务的复制设置的关键设置。 但是,特定于 InnoDB 或其他存储引擎的其他设置,尤其是与刷新或同步相关的设置,也会产生影响。 请务必检查并应用存储引擎提出的有关崩溃安全设置的建议。

副本上的以下设置组合对于意外停止最具弹性:

  • 当使用基于 GTID 的复制时 (gtid_mode=ON),请设置 SOURCE_AUTO_POSITION=1,这会激活与源的连接的 GTID 自动定位,以自动识别和检索丢失的事务。 此选项是使用 CHANGE REPLICATION SOURCE TO 语句设置的。 如果副本有多个复制通道,则需要为每个通道单独设置此选项。 有关 GTID 自动定位如何工作的详细信息,请参阅第 19.1.3.3 节“GTID 自动定位”。 当使用基于文件位置的复制时,不使用 SOURCE_AUTO_POSITION=1,而是使用二进制日志位置或中继日志位置来控制复制开始的位置。
  • 当使用基于 GTID 的复制时 (gtid_mode=ON),设置 GTID_ONLY=1,这使得副本在恢复过程中仅使用 GTID,并停止在复制元数据存储库中保留二进制日志和中继日志文件名和文件位置。 此选项是使用 CHANGE REPLICATION SOURCE TO 语句设置的。 如果副本有多个复制通道,则需要为每个通道单独设置此选项。 当 GTID_ONLY=1 时,在恢复期间,文件位置信息将被忽略,GTID 自动跳过用于跳过已提供的事务,而不是识别正确的文件位置。 如果使用relay_log_purge 的默认设置清除中继日志,则此策略会更有效,这意味着只需要检查一个中继日志文件。
  • 设置sync_relay_log=1,这指示复制接收器线程在每个接收到的事务写入其中后将中继日志同步到磁盘。 这意味着从源二进制日志(在应用程序元数据存储库中)读取的当前位置的副本记录永远不会领先于中继日志中保存的事务记录。 请注意,虽然此设置是最安全的,但由于涉及磁盘写入次数,它也是最慢的。 当sync_relay_log > 1 或sync_relay_log=0(其中同步由操作系统处理)时,如果副本意外停止,可能会出现尚未同步到磁盘的已提交事务。 如果恢复副本根据上次同步到磁盘的中继日志中的信息尝试再次检索并应用事务而不是跳过它们,则此类事务可能会导致恢复过程失败。 设置sync_relay_log = 1对于多线程副本尤其重要,如果无法使用中继日志中的信息填充事务序列中的间隙,则恢复过程将失败。 对于单线程副本,如果应用程序元数据存储库中没有相关信息,则恢复过程仅需要使用中继日志。
  • 设置innodb_flush_log_at_trx_commit=1,即在每个事务提交之前将InnoDB日志同步到磁盘。 此设置是默认设置,可确保 InnoDB 表和 InnoDB 日志保存在磁盘上,以便不再需要中继日志中有关事务的信息。 结合设置sync_relay_log=1,该设置进一步保证了InnoDB表和InnoDB日志的内容始终与中继日志的内容一致,这样清除中继日志文件不会导致副本的无法填充的间隙。 意外停止时的交易历史记录。
  • 设置relay_log_info_repository = TABLE,将复制SQL线程位置存储在InnoDB表mysql.slave_relay_log_info中,并与事务提交一起更新,以确保记录始终准确。 此设置为默认设置; FILE 已弃用。 系统变量本身也已被弃用,因此忽略它并允许它采用默认值。 如果使用 FILE,则信息存储在数据目录中的文件中,该文件在应用事务后更新。 这会产生与源失去同步的风险,具体取决于副本在处理事务的哪个阶段停止,甚至导致文件本身损坏。 当relay_log_info_repository = FILE时,不能保证恢复。
  • 设置relay_log_recovery = ON,这将在服务器启动后立即启用自动中继日志恢复。 此全局变量默认为 OFF,并且在运行时是只读的,但可以在副本意外停止后在副本启动时使用 --relay-log-recovery 选项将其设置为 ON。 请注意,此设置会忽略现有的中继日志文件,以防它们损坏或不一致。 中继日志恢复过程启动一个新的中继日志文件,并从应用程序元数据存储库中记录的复制 SQL 线程位置开始从源获取事务。 随着时间的推移,以前的中继日志文件将被副本的正常清除机制删除。

对于多线程副本,设置relay_log_recovery = ON会自动处理从中继日志执行的事务序列中的任何不一致和间隙。 当使用基于文件位置的复制时,可能会出现这些间隙。 中继日志恢复过程使用与 START REPLICA UNTIL SQL_AFTER_MTS_GAPS 语句相同的方法处理间隙。 当副本达到一致的无间隙状态时,中继日志恢复过程将继续从复制 SQL 线程位置开始从源获取更多事务。 当使用基于GTID的复制时,多线程副本首先检查MASTER_AUTO_POSITION是否设置为ON,如果是,则省略计算应该跳过或不跳过的事务的步骤,从而不需要旧的中继日志 用于恢复过程。