为了使复制能够对服务器的意外停止(有时被描述为崩溃安全)具有弹性,副本必须能够在停止之前恢复其状态。本节介绍复制过程中副本意外停止的影响,以及如何配置副本以获得最佳恢复机会以继续复制。
在副本意外停止后,重新启动时,复制 SQL 线程必须恢复有关已执行哪些事务的信息。恢复所需的信息存储在副本的应用程序元数据存储库中。从 MySQL 8.0 开始,这个存储库默认创建为一个InnoDB
名为
mysql.slave_relay_log_info
. 通过使用这个事务性存储引擎,信息总是可以在重启时恢复。对应用程序元数据存储库的更新与事务一起提交,这意味着记录在该存储库中的副本进度信息始终与已应用到数据库的内容一致,即使在服务器意外停机的情况下也是如此。有关应用程序元数据存储库的更多信息,请参阅
第 17.2.4 节,“中继日志和复制元数据存储库”。
DML 事务和原子 DDL 更新
mysql.slave_relay_log_info
表中副本的应用程序元数据存储库中的复制位置,同时将更改应用到数据库,作为原子操作。在所有其他情况下,包括非完全原子的 DDL 语句和不支持原子 DDL 的豁免存储引擎,mysql.slave_relay_log_info
如果服务器意外停止,表可能会丢失与复制数据相关的更新。在这种情况下恢复更新是一个手动过程。有关 MySQL 8.0 中原子 DDL 支持的详细信息,以及某些语句复制的结果行为,请参阅第 13.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
|MASTER_AUTO_POSITION=1
,它激活 GTID 自动定位以连接到源以自动识别和检索丢失的事务。此选项使用CHANGE REPLICATION SOURCE TO
语句(来自 MySQL 8.0.23)或CHANGE MASTER TO
语句(MySQL 8.0.23 之前)设置。如果副本有多个复制通道,则需要为每个通道单独设置此选项。有关 GTID 自动定位如何工作的详细信息,请参阅第 17.1.3.3 节,“GTID 自动定位”。当使用基于文件位置的复制时,SOURCE_AUTO_POSITION=1
|MASTER_AUTO_POSITION=1
不使用,而是使用二进制日志位置或中继日志位置来控制复制开始的位置。从 MySQL 8.0.27 开始,当使用基于 GTID 的复制时 (
gtid_mode=ON
),设置GTID_ONLY=1
,这使得副本在恢复过程中仅使用 GTID,并停止在复制元数据存储库中保留二进制日志和中继日志文件名和文件位置。此选项使用CHANGE REPLICATION SOURCE TO
语句设置。如果副本有多个复制通道,则需要为每个通道单独设置此选项。和GTID_ONLY=1
,在恢复期间,文件位置信息被忽略,GTID 自动跳过用于跳过已经提供的事务,而不是识别正确的文件位置。如果您使用 的默认设置清除中继日志,则此策略更有效relay_log_purge
,这意味着只需要检查一个中继日志文件。Set
sync_relay_log=1
,它指示复制接收器线程在每个接收到的事务写入后将中继日志同步到磁盘。这意味着从源的二进制日志(在应用程序元数据存储库中)读取的当前位置的副本记录永远不会领先于保存在中继日志中的事务记录。请注意,虽然此设置是最安全的,但由于涉及的磁盘写入次数,它也是最慢的。与sync_relay_log > 1
或sync_relay_log=0
(其中同步由操作系统处理),如果副本意外停止,则可能有尚未同步到磁盘的已提交事务。如果恢复副本基于它在上次同步到磁盘的中继日志中的信息,尝试再次检索和应用事务而不是跳过它们,则此类事务可能导致恢复过程失败。环境sync_relay_log=1
对于多线程副本尤为重要,如果无法使用中继日志中的信息填充事务序列中的间隙,则恢复过程将失败。对于单线程副本,如果应用程序元数据存储库中没有相关信息,恢复过程只需要使用中继日志。Set
innodb_flush_log_at_trx_commit=1
,InnoDB
在提交每个事务之前将日志同步到磁盘。此设置是默认设置,可确保InnoDB
表和InnoDB
日志保存在磁盘上,因此不再需要中继日志中有关事务的信息。结合设置sync_relay_log=1
,这个设置进一步保证了InnoDB
表和InnoDB
日志的内容在任何时候都与中继日志的内容一致,这样清除中继日志文件就不会在副本的交易历史中造成无法填补的空白。意外停止事件。Set
relay_log_info_repository = TABLE
,将复制SQL线程位置存储在InnoDB
表中mysql.slave_relay_log_info
,并与事务提交一起更新,以确保记录始终准确。此设置是 MySQL 8.0 的默认设置,并且FILE
已弃用。从 MySQL 8.0.23 开始,系统变量本身的使用已被弃用,因此忽略它并允许它默认。如果FILE
设置,这是早期版本中的默认设置,信息存储在数据目录中的文件中,该文件在应用事务后更新。这会产生与源失去同步的风险,具体取决于副本在处理事务的哪个阶段停止,甚至损坏文件本身。使用设置relay_log_info_repository = FILE
,无法保证恢复。Set
relay_log_recovery = ON
,它在服务器启动后立即启用自动中继日志恢复。此全局变量默认为OFF
并且在运行时是只读的,但您可以在副本意外停止后使用副本启动ON
时的 选项将其设置为。--relay-log-recovery
请注意,此设置会忽略现有的中继日志文件,以防它们损坏或不一致。中继日志恢复进程启动一个新的中继日志文件,并从记录在应用程序元数据存储库中的复制 SQL 线程位置开始从源获取事务。副本的正常清除机制会随着时间的推移删除以前的中继日志文件。
对于多线程副本,设置
relay_log_recovery = ON
会自动处理从中继日志执行的事务序列中的任何不一致和间隙。当使用基于文件位置的复制时,可能会出现这些间隙。(有关更多详细信息,请参阅
第 17.5.1.34 节,“复制和事务不一致”。)中继日志恢复过程使用与START
REPLICA UNTIL SQL_AFTER_MTS_GAPS
(或在 MySQL 8.0.22 之前,START SLAVE 而不是 START REPLICA)语句会。当副本达到一致的无间隙状态时,中继日志恢复过程继续从复制 SQL 线程位置开始从源获取更多事务。当使用基于 GTID 的复制时,从 MySQL 8.0.18 开始,多线程副本首先检查是否
MASTER_AUTO_POSITION
设置为
ON
,如果是,则省略计算应该跳过或不跳过的事务的步骤,以便旧的中继日志恢复过程不需要。