为了使复制能够抵御服务器意外停止(有时称为崩溃安全),副本必须能够在停止之前恢复其状态。本节介绍副本在复制期间意外停止的影响,以及如何配置副本以最大限度地提高恢复以继续复制的可能性。
在副本意外停止后,重新启动时,复制 SQL 线程必须恢复有关哪些事务已执行的信息。用于恢复的信息存储在副本的应用程序元数据存储库中。此存储库默认情况下创建为一个名为 mysql.slave_relay_log_info
的 InnoDB
表。通过使用此事务性存储引擎,信息始终可在重新启动时恢复。对应用程序元数据存储库的更新与事务一起提交,这意味着存储库中记录的副本进度信息始终与已应用到数据库的内容保持一致,即使在发生意外服务器停止的情况下也是如此。有关应用程序元数据存储库的更多信息,请参见 第 19.2.4 节,“中继日志和复制元数据存储库”。
DML 事务以及原子 DDL 会在将更改应用到数据库的同时,更新 mysql.slave_relay_log_info
表中副本的应用程序元数据存储库中的复制位置,作为一个原子操作。在所有其他情况下,包括非完全原子的 DDL 语句和不支持原子 DDL 的免责存储引擎,如果服务器意外停止,mysql.slave_relay_log_info
表可能缺少与已复制数据相关的更新。在这种情况下,恢复更新是一个手动过程。有关 MySQL 8.4 中原子 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
,这会指示复制接收器线程在将接收到的每个事务写入中继日志后将其同步到磁盘。这意味着副本从源的二进制日志中读取的当前位置记录(在应用程序元数据存储库中)永远不会超过保存在中继日志中的事务记录。请注意,尽管此设置是最安全的,但由于涉及的磁盘写入次数众多,它也是最慢的。使用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
会自动处理从中继日志执行的事务序列中出现的任何不一致和间隙。当使用基于文件位置的复制时,会发生这些间隙。(有关更多详细信息,请参见 第 19.5.1.34 节,“复制和事务不一致”。)中继日志恢复过程使用与 START REPLICA UNTIL SQL_AFTER_MTS_GAPS
语句相同的方法处理间隙。当副本达到一致的无间隙状态时,中继日志恢复过程将继续从源获取更多事务,从复制 SQL 线程位置开始。当使用基于 GTID 的复制时,多线程副本首先检查 SOURCE_AUTO_POSITION
是否设置为 ON
,如果是,则省略计算应跳过或不应跳过的交易的步骤,因此旧的中继日志不需要用于恢复过程。