为了使复制对服务器意外停止具有弹性(有时称为崩溃安全),副本必须能够在停止前恢复其状态。 本节描述了副本在复制过程中意外停止的影响,以及如何配置副本以获得最佳恢复机会继续复制。
在副本意外停止后,重新启动时,复制 SQL 线程必须恢复已经执行的事务信息。该信息存储在副本的应用程序元数据存储库中。该存储库默认创建为 InnoDB
表,名为 mysql.slave_relay_log_info
。通过使用事务存储引擎,该信息总是可以在重新启动时恢复。事务的更新与事务一起提交,这意味着副本的进度信息记录在该存储库中总是与数据库中已应用的内容一致,即使在服务器意外停止的情况下。有关应用程序元数据存储库的更多信息,请参阅 第 19.2.4 节,“中继日志和复制元数据存储库”。
DML 事务和原子 DDL 更新副本的应用程序元数据存储库中的复制位置,在 mysql.slave_relay_log_info
表中,连同将更改应用于数据库,作为原子操作。在所有其他情况下,包括不支持原子 DDL 的存储引擎,mysql.slave_relay_log_info
表可能缺少与复制数据相关的更新,如果服务器意外停止。恢复这些更新是一个手动过程。有关 MySQL 8.3 中原子 DDL 支持的详细信息,以及对某些语句的复制行为,请参阅 第 15.1.1 节,“原子数据定义语句支持”。
副本从意外停止恢复的过程因副本的配置而异。恢复过程的细节受到复制方法、副本是否为单线程或多线程、相关系统变量的设置等因素的影响。总的目标是确定副本在意外停止前已经应用于数据库的交易,并检索和应用副本在意外停止后遗漏的交易。
-
对于基于 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
,指示复制接收器线程在每个事务写入中继日志后将其同步到磁盘上。这意味着副本从源的二进制日志中读取的当前位置记录(在applier元数据存储库中)永远不会超出中继日志中保存的事务记录。注意,虽然这项设置是最安全的,但也是最慢的,因为涉及到许多磁盘写入操作。使用sync_relay_log > 1
或sync_relay_log=0
(其中同步由操作系统处理),在副本意外停止的情况下,可能会有已提交的事务没有同步到磁盘。这些事务可能会导致恢复过程失败,因为恢复副本根据中继日志中最后同步的信息尝试检索和应用这些事务,而不是跳过它们。对于多线程副本,设置sync_relay_log=1
尤其重要,因为恢复过程将失败,如果无法使用中继日志中的信息填充事务序列中的间隙。对于单线程副本,恢复过程只需要使用中继日志,如果applier元数据存储库中没有相关信息。 -
设置
innodb_flush_log_at_trx_commit=1
,将InnoDB
日志同步到磁盘之前每个事务提交。这项设置,作为默认设置,确保InnoDB
表和InnoDB
日志被保存到磁盘上,以便不再需要中继日志中的信息来记录事务。与sync_relay_log=1
结合使用,这项设置进一步确保InnoDB
表和InnoDB
日志的内容始终与中继日志的内容保持一致,以便在副本意外停止的情况下,purge中继日志文件不会导致事务历史记录中的间隙无法填充。 -
设置
relay_log_info_repository = TABLE
,它将复制SQL线程位置存储在InnoDB
表mysql.slave_relay_log_info
中,并在事务提交时更新,以确保记录始终准确。这是默认设置;FILE
已弃用。该系统变量本身也已弃用,因此请省略它并允许它采用默认值。如果使用FILE
,信息将存储在数据目录中的文件中,该文件将在事务应用后更新。这会在复制源停止时创建同步风险,或者文件本身可能会损坏。使用relay_log_info_repository = FILE
,恢复不能保证。 -
设置
relay_log_recovery = ON
,启用自动relay日志恢复,立即在服务器启动后执行。此全局变量默认为OFF
,在运行时为只读,但您可以使用--relay-log-recovery
选项在复制服务器启动时设置为ON
,以便在意外停止复制服务器时恢复。请注意,该设置将忽略现有的relay日志文件,以防止它们损坏或不一致。relay日志恢复过程将启动一个新的relay日志文件,并从源开始记录事务,自applier元数据存储库中的复制SQL线程位置。以前的relay日志文件将被复制服务器的正常清除机制删除。
对于多线程复制服务器,设置 relay_log_recovery = ON
将自动处理relay日志中的不一致和间隙,这些间隙可能出现在基于文件位置的复制中。(有关详细信息,请参阅 第 19.5.1.34 节,“复制和事务不一致”。)relay日志恢复过程使用与 START REPLICA UNTIL SQL_AFTER_MTS_GAPS
语句相同的方法来处理间隙。当复制服务器达到一致的无间隙状态时,relay日志恢复过程将继续从源开始记录事务,自复制SQL线程位置。当使用GTID-based复制时,多线程复制服务器首先检查 MASTER_AUTO_POSITION
是否设置为 ON
,如果是,则跳过计算应跳过或不跳过的事务步骤,以便不需要旧relay日志来恢复过程。