25.7.8 NDB 集群复制中的故障转移实现
如果主Cluster 复制过程失败,可能会切换到次要复制通道。以下是完成此操作所需的步骤。
-
获取最近一次全局检查点(GCP)的时间。也就是说,您需要确定来自复制集群的最新纪元,从该集群的副本上可以使用以下查询找到在
ndb_apply_status
表中:mysqlR'> SELECT @latest:=MAX(epoch) -> FROM mysql.ndb_apply_status;
在循环复制拓扑结构中,源和每个主机上的副本运行时,当使用
ndb_log_apply_status=1
,NDB 集群的纪元会写入到副本的二进制日志中。这意味着ndb_apply_status
表包含了该主机上的副本以及任何作为其他主机上复制源服务器的副本的信息。在这种情况下,您需要确定该副本上最新的纪元,排除任何其他副本在其二进制日志中未列出的纪元,这些纪元不在
CHANGE REPLICATION SOURCE TO
用于设置此副本的语句中指定的IGNORE_SERVER_IDS
选项中。排除这些纪元的原因是,mysql. ndb_apply_status
表中的行,其服务器ID在CHANGE REPLICATION SOURCE TO
用于准备此副本的源设置时指定了IGNORE_SERVER_IDS
列表中的服务器ID,也被认为来自本地服务器,除了具有副本自身服务器ID的行。您可以从SHOW REPLICA STATUS
的输出中检索此列表,称为Replicate_Ignore_Server_Ids
。我们假设您已经获得了这个列表,并将其用作查询中显示的ignore_server_ids
的替代品,该查询类似于之前版本的查询,选择最大纪元并将其存储在名为@latest
的变量中:mysqlR'> SELECT @latest:=MAX(epoch) -> FROM mysql.ndb_apply_status -> WHERE server_id NOT IN (ignore_server_ids);
有时,使用要包括的服务器ID列表和
server_id IN
在前述查询的WHERE子句中可能更简单或高效(或者两者都有)。server_id_list
-
使用步骤1中获得的信息,从源集群上的
ndb_
binlog_index
表中检索相应记录。您可以使用以下查询来从
ndb_binlog_index
表中检索所需的记录:mysqlS'> SELECT -> @file:=SUBSTRING_INDEX(next_file, '/', -1), -> @pos:=next_position -> FROM mysql.ndb_binlog_index -> WHERE epoch = @latest;
这些是自源主复制通道失败以来的源上保存的记录。我们在这里使用了一个用户变量
@latest
来表示步骤1中的值。当然,无法让一个 mysqld 实例直接访问另一个服务器实例上的用户变量。这些值必须在第二个查询中手动插入或通过应用程序“插入”。Important您必须确保复制 mysqld 实例在执行
START REPLICA
之前使用--replica-skip-errors=ddl_exist_errors
启动。否则,复制可能会因为重复的DDL错误而停止。 -
现在可以通过在次要副本服务器上运行以下查询来同步次要通道:
mysqlR'> CHANGE REPLICATION SOURCE TO -> SOURCE_LOG_FILE='@file', -> SOURCE_LOG_POS=@pos;
再次,我们使用了用户变量(在这种情况下
@file
和@pos
)来表示步骤2中获得的值并应用于步骤3;实际上,这些值必须手动插入或使用一个可以访问涉及的两个服务器的应用程序。Note@file
是一个字符串值,如'/var/log/mysql/replication-source-bin.00001'
,因此在 SQL 或应用程序代码中使用时必须加引号。然而,@pos
所表示的值不需要加引号。尽管 MySQL 通常尝试将字符串转换为数字,这种情况是个例外。 -
您现在可以在次要副本上通过在次要副本上发出适当命令来启动复制:mysqld:
mysqlR'> START REPLICA;
一旦次要复制通道激活,您可以调查主副本的故障并进行修复。执行此操作所需的确切步骤取决于主副本失败的原因。
仅在主副本失败时才启动次要复制通道。同时运行多个复制通道可能会在副本上创建不想要的重复记录。
如果故障仅限于单个服务器,那么理论上应该可以从 S
到 R'
进行复制,或者从 S'
到 R
。