19.4.2 处理副本意外停止
为了使复制能够对服务器意外停止(有时称为崩溃安全)提供弹性, replica 在意外停止时必须能够恢复其状态。这个部分描述了副本在复制过程中意外停止的影响,以及如何配置副本以确保恢复继续复制。
在副本意外停止后,重新启动时,replication SQL 线程必须恢复已经执行的交易信息。恢复所需的信息存储在副本的应用程序元数据存储库中。这個存储库默认情况下是一个名为 InnoDB
表的 mysql.slave_relay_log_info
。使用事务存储引擎,这个信息总是可以在重新启动时恢复。更新应用程序元数据存储库的更新与事务一起提交,这意味着副本的进度信息记录在该存储库中总是与已经应用到数据库的内容一致,即使在意外服务器停止的情况下。关于应用程序元数据存储库的更多信息,请见 第19.2.4节,“Relay Log and Replication Metadata Repositories”。
DML 交易和原子 DDL 更新副本的应用程序元数据存储库中的复制位置在 mysql.slave_relay_log_info
表中,同时应用于数据库中的更改,以原子操作方式。在所有其他情况下,包括非原子 DDL 语句和不支持原子 DDL 的存储引擎,mysql.slave_relay_log_info
表可能会缺少与复制数据相关的更新。如果服务器意外停止,恢复更新需要手动过程。关于 MySQL 8.4 中的原子 DDL 支持和对某些语句的复制行为,请见 第15.1.1节,“Atomic Data Definition Statement Support”。
副本恢复过程的细节取决于副本的配置。恢复过程的细节受到副本的方法、线程数和相关系统变量的设置的影响。恢复过程的总目标是确定副本数据库中已经应用的交易,并从意外停止后缺失的交易中恢复。
-
对于 GTID 基础的复制,恢复过程需要 GTIDs 已经收到的或已经提交的交易。可以从源服务器使用 GTID 自动定位,自动将源服务器的交易与副本的交易进行比较,确定缺失的交易。
-
对于文件位置基础的复制,恢复过程需要准确的复制 SQL 线程(应用程序)位置,显示副本上最后一个已应用的交易。基于该位置,复制 I/O 线程(接收器)从源服务器的二进制日志中检索所有应该在副本上应用的交易从该点开始。
使用基于GTID的复制可以使复制配置更加容易地抵抗意外中断。GTID自动定位意味着副本可以可靠地识别和检索缺失的事务,即使在事务序列中存在空缺。
以下信息提供了不同类型副本的设置组合,以确保在复制控制范围内的恢复。
一些因素超出了复制控制的范围,可以影响复制恢复过程和总体复制状态。特别是,影响单个存储引擎恢复过程的设置可能会导致在副本意外中断时事务丢失,从而不可用于复制恢复过程。以下列表中的innodb_flush_log_at_trx_commit=1
设置是使用InnoDB
事务的关键设置。然而,对于InnoDB
或其他存储引擎的设置,特别是flushing或同步相关的设置,也可能会对恢复过程产生影响。总是检查并应用您的选择存储引擎关于crash-safe设置的建议。
副本中最具抵抗意外中断的设置组合是:
-
当使用基于GTID的复制时(
gtid_mode=ON
),设置SOURCE_AUTO_POSITION=1
,激活连接到源的GTID自动定位,以自动识别和检索缺失的事务。该选项使用CHANGE REPLICATION SOURCE TO
语句设置。如果副本有多个复制通道,您需要为每个通道设置该选项。关于GTID自动定位的详细信息,请见第19.1.3.3节,“GTID Auto-Positioning”。当使用基于文件位置的复制时,SOURCE_AUTO_POSITION=1
不使用,而是使用二进制日志位置或中继日志位置来控制复制开始位置。 -
当使用基于GTID的复制时(
gtid_mode=ON
),设置GTID_ONLY=1
,使从库在恢复过程中只使用GTID,并停止在复制元数据存储库中持久化二进制日志和中继日志文件名和文件位置。这选项使用CHANGE REPLICATION SOURCE TO
语句设置。如果从库有多个复制通道,需要为每个通道单独设置该选项。使用GTID_ONLY=1
时,在恢复过程中将忽略文件位置信息,并使用GTID自动跳过已经提供的交易,而不是确定正确的文件位置。这一策略在 purge relay logs 使用默认设置relay_log_purge
时是更高效的,因为只需要检查一个中继日志文件。 -
设置
sync_relay_log=1
,使复制接收线程在将每个事务写入relay log后将其同步到磁盘。这意味着从库的记录将永远不会超出源服务器的二进制日志(在applier元数据存储库中)中的当前位置记录。请注意,这个设置是最安全的,但也是最慢的,因为涉及到大量磁盘写入。使用sync_relay_log > 1
或sync_relay_log=0
(在操作系统中处理同步),在从库意外中断时可能会有未同步的事务,这些事务可能会导致恢复过程失败。如果恢复的从库,基于relay log中的信息,尝试重新应用事务,而不是跳过它们。设置sync_relay_log=1
对多线程从库特别重要,因为恢复过程失败如果不能使用relay log中的信息填充事务序列的空缺。对于单线程从库,恢复过程只需要使用relay log,如果相关信息不可用在applier元数据存储库中。 -
设置
innodb_flush_log_at_trx_commit=1
,该设置将InnoDB
日志同步到磁盘前每个事务提交。这是默认设置,确保InnoDB
表和InnoDB
日志在磁盘上保存,以避免在relay日志中记录事务的需求。与设置sync_relay_log=1
组合使用,这样可以确保InnoDB
表和InnoDB
日志与relay日志的内容始终一致,以避免在事件中无法填充的gap在副本的交易历史中。 -
设置
relay_log_info_repository = TABLE
,该设置将replication SQL线程的位置存储在InnoDB
表mysql.slave_relay_log_info
中,并在事务提交时更新,以确保记录始终准确。这是默认设置;FILE
已弃用。该系统变量本身也已弃用,因此忽略它并让它默认。使用FILE
将信息存储在数据目录中的文件中,并在事务应用后更新。这将导致在处理事务时可能会丢失同步或文件本身的损坏。使用relay_log_info_repository = FILE
,恢复是不可保证的。 -
设置
relay_log_recovery = ON
,该设置启用在服务器启动后立即启动relay日志恢复。这是全局变量,读取时为只读,但可以使用--relay-log-recovery
选项在副本启动时启用。注意,这个设置忽略现有relay日志文件,如果它们是损坏或不一致的。relay日志恢复过程将启动新的relay日志文件,并从源开始获取事务,开始于applier元数据存储库中的replication SQL线程位置。之前的relay日志文件将在副本的正常清理机制中被删除。
对于多线程副本,设置relay_log_recovery = ON
自动处理从中继日志中执行的交易序列中的任何不一致和空隙。这些空隙可能会在使用基于文件位置的复制时出现。 (更多信息,请见第19.5.1.34节,“复制和事务不一致”。)中继日志恢复过程使用与START REPLICA UNTIL SQL_AFTER_MTS_GAPS
语句相同的方法来处理空隙。当副本达到一致的空隙状态后,中继日志恢复过程继续从源开始,从replication SQL线程的当前位置获取更多事务。当使用GTID-基于的复制时,多线程副本首先检查SOURCE_AUTO_POSITION
是否设置为ON
,如果是,它将跳过计算应该跳过或不跳过的交易,以免使用老的中继日志来恢复过程。