为了使复制能够在服务器意外停止时具有弹性(有时称为崩溃安全),副本必须能够恢复其停止前的状态。本节介绍副本在复制期间意外停止的影响,以及如何配置副本以最大程度地提高恢复并继续复制的可能性。
在副本意外停止后,重新启动时,复制 SQL 线程必须恢复有关哪些事务已经执行的信息。恢复所需的信息存储在副本的应用程序元数据存储库中。此存储库默认情况下作为 InnoDB
表创建,名为 mysql.slave_relay_log_info
。通过使用此事务性存储引擎,信息在重新启动时始终可以恢复。对应用程序元数据存储库的更新与事务一起提交,这意味着该存储库中记录的副本进度信息始终与已应用到数据库的信息一致,即使在服务器意外停止的情况下也是如此。有关应用程序元数据存储库的更多信息,请参见 第 19.2.4 节“中继日志和复制元数据存储库”。
DML 事务以及原子 DDL 会在将更改应用到数据库的同时更新副本的应用程序元数据存储库中的 mysql.slave_relay_log_info
表中的复制位置,作为一个原子操作。在所有其他情况下,包括不完全原子的 DDL 语句以及不支持原子 DDL 的豁免存储引擎,如果服务器意外停止,mysql.slave_relay_log_info
表可能会缺少与已复制数据相关的更新。在这种情况下,恢复更新是一个手动过程。有关 MySQL 9.0 中原子 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.35 节,“复制和事务不一致”。)中继日志恢复过程使用与 START REPLICA UNTIL SQL_AFTER_MTS_GAPS
语句相同的方法处理间隙。当副本达到一致的无间隙状态时,中继日志恢复过程将继续从源获取更多事务,从复制 SQL 线程位置开始。当使用基于 GTID 的复制时,多线程副本会首先检查 SOURCE_AUTO_POSITION
是否设置为 ON
,如果是,则省略计算应跳过或不应跳过的交易的步骤,因此旧的中继日志不是必需的恢复过程。