本节讨论使用 NDB 集群复制时的已知问题。
源和副本之间的连接丢失。 连接丢失可能发生在源集群 SQL 节点和副本集群 SQL 节点之间,也可能发生在源 SQL 节点和源集群数据节点之间。在后一种情况下,这可能是由于数据节点事件缓冲区溢出;如果 SQL 节点响应太慢,它可能被集群删除(这可以通过调整 MaxBufferedEpochs
和 TimeBetweenEpochs
配置参数来控制)。如果发生这种情况,新数据可能被插入到源集群中,而不被记录在源 SQL 节点的二进制日志中。因此,为了保证高可用性,非常重要的是维护一个备份复制通道,监控主通道,并在必要时 failover 到次要复制通道,以保持副本集群与源集群同步。NDB 集群本身不设计监控复制状态或提供故障转移;为此,需要外部应用程序。
源 SQL 节点在连接或重新连接到源集群时发出“gap”事件。(gap 事件是一种“incident 事件”,指的是影响数据库内容但无法轻松表示为更改集的事件。示例包括服务器故障、数据库重新同步、一些软件更新和一些硬件更改。)当副本遇到复制日志中的 gap 时,它将停止并显示错误消息。该消息可在 SHOW REPLICA STATUS
的输出中找到,表明 SQL 线程由于复制流中的事件而停止,并且需要手动干预。请参阅 第 25.7.8 节,“使用 NDB 集群复制实现故障转移”,以获取更多关于在这种情况下该做什么的信息。
因为 NDB 集群本身不设计监控复制状态或提供故障转移,因此,如果高可用性是副本服务器或集群的要求,那么您必须设置多个复制线路,监控主复制线路上的源 mysqld,并准备在必要时 failover 到次要线路。必须手动或通过第三方应用程序来实现这种设置。有关实现这种设置的信息,请参阅 第 25.7.7 节,“使用两个复制通道进行 NDB 集群复制” 和 第 25.7.8 节,“使用 NDB 集群复制实现故障转移”。
如果您从独立的 MySQL 服务器复制到 NDB 集群,一般来说一个通道就足够。
循环复制。 NDB 集群复制支持循环复制,如下所示的示例所示。复制设置涉及三个 NDB 集群,编号为 1、2 和 3,其中 Cluster 1 作为 Cluster 2 的复制源,Cluster 2 作为 Cluster 3 的源,Cluster 3 作为 Cluster 1 的源,从而形成一个循环。
只要满足以下条件,循环复制就支持这些集群:
-
所有源和副本集群的 SQL 节点相同。
-
所有源和副本集群的 SQL 节点都启用了系统变量
log_replica_updates
。
这种循环复制设置如以下图所示:
在这个场景中,Cluster 1 中的 SQL 节点 A 将数据复制到 Cluster 2 中的 SQL 节点 C;SQL 节点 C 将数据复制到 Cluster 3 中的 SQL 节点 E;SQL 节点 E 将数据复制到 Cluster 1 中的 SQL 节点 A。在其他 words,复制线(图中的弯曲箭头)直接连接所有用作源和副本的 SQL 节点。
也可以设置圆形复制,其中不是所有源 SQL 节点都是副本,如下所示:
在这种情况下,每个集群中的不同 SQL 节点用作源和副本。但是,您不能在任何 SQL 节点上启用 log_replica_updates 系统变量。这类圆形复制方案对于 NDB 集群,复制线(图中的弯曲箭头)是断开的,应该是可能的,但尚未经过彻底测试,因此仍然是实验性的。
NDB 存储引擎使用 幂等执行模式,该模式抑制了重复键和其他错误,这些错误否则会破坏圆形复制的 NDB 集群。这相当于将系统变量 replica_exec_mode
设置为 IDEMPOTENT
,尽管这在 NDB 集群复制中不是必要的,因为 NDB 集群自动设置该变量并忽略任何明确设置尝试。
NDB 集群复制和主键。 如果节点失败,在没有主键的 NDB 表中复制时,仍然可能出现错误。这是因为可能会插入重复行。在这种情况下,强烈建议所有要复制的 NDB 表都具有明确的主键。
NDB 集群复制和唯一键。 在 NDB 集群的旧版本中,对唯一键列的更新操作可能会导致复制时的重复键错误。这个问题现在已经解决了,因为 NDB 集群现在可以延迟唯一键检查,直到所有表行更新完成。
这种延迟约束检查目前仅支持 NDB 集群。因此,从 NDB 集群到其他存储引擎(如 InnoDB 或 MyISAM)复制时,更新唯一键仍然不支持。
可以使用 NDB 表(如 t)来说明没有延迟唯一键检查时复制的问题,如下所示:
CREATE TABLE t (
p INT PRIMARY KEY,
c INT,
UNIQUE KEY u (c)
) ENGINE NDB;
INSERT INTO t
VALUES (1,1), (2,2), (3,3), (4,4), (5,5);
以下 UPDATE
语句在源上成功,因为受影响的行按照 ORDER BY 选项确定的顺序进行处理:
UPDATE t SET c = c - 1 ORDER BY p;
同样的语句在副本上失败,出现重复键错误或其他约束违规,因为行更新的顺序是按分区进行的,而不是整个表。
每个 NDB 表在创建时隐式地按键分区。请参阅 第 26.2.5 节,“KEY 分区”,以获取更多信息。
GTIDs 不支持。 使用全局事务 ID 的复制与 NDB 存储引擎不兼容,不支持。启用 GTIDs 可能会导致 NDB 集群复制失败。
使用 --initial 重新启动。 使用 --initial
选项重新启动集群将从 0
开始 GCI 和 epoch 号码序列。(这在 NDB 集群中普遍适用,而不仅限于涉及集群的复制场景。) 在这种情况下,参与复制的 MySQL 服务器应该重新启动。然后,您应该使用 RESET BINARY LOGS AND GTIDS
和 RESET REPLICA
语句来清除无效的 ndb_binlog_index
和 ndb_apply_status
表,分别。
从 NDB 到其他存储引擎的复制。 可以将源 NDB
表复制到使用不同存储引擎的表,考虑以下限制:
-
多源和循环复制不受支持(源和副本上的表必须使用
NDB
存储引擎以使其生效)。 -
使用不执行二进制日志记录的存储引擎的表在副本上需要特殊处理。
-
使用非事务性存储引擎的表在副本上也需要特殊处理。
-
源 mysqld 必须使用
--ndb-log-update-as-write=0
或--ndb-log-update-as-write=OFF
启动。
接下来几段落提供了每个问题的更多信息。
从 NDB 到其他存储引擎的复制不支持多源。 从 NDB
到不同存储引擎的复制关系必须是一对一的。这意味着双向或循环复制在 NDB 集群和其他存储引擎之间不受支持。
此外,从 NDB
到不同存储引擎的复制不能配置多个复制通道。(NDB 集群数据库 可以 同时复制到多个 NDB 集群数据库。)如果源使用 NDB
表,仍然可以让多个 MySQL 服务器维护二进制日志的所有更改,但为了使副本更改源(故障转移),新的源副本关系必须在副本上明确定义。
将 NDB 表复制到不执行二进制日志记录的存储引擎。 如果您尝试从 NDB 集群复制到使用不执行二进制日志记录的存储引擎的副本,复制过程将中止并显示错误 Binary logging not possible ... Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging(错误 1595)。可以通过以下方式解决此问题:
-
在副本上关闭二进制日志记录。 可以通过设置
sql_log_bin = 0
来实现。 -
更改 mysql.ndb_apply_status 表的存储引擎。 使该表使用不执行二进制日志记录的引擎也可以消除冲突。这可以通过在副本上执行语句
ALTER TABLE mysql.ndb_apply_status ENGINE=MyISAM
来实现。 -
在副本上过滤 mysql.ndb_apply_status 表的更改。 可以通过在副本上启动
--replicate-ignore-table=mysql.ndb_apply_status
来实现。如果您需要忽略其他表,可以使用适当的--replicate-wild-ignore-table
选项代替。
您不应该 禁用 复制或二进制日志记录 mysql.ndb_apply_status
或更改用于此表的存储引擎,当从一个 NDB 集群复制到另一个时。请参阅 复制和二进制日志过滤规则与 NDB 集群之间的复制,以获取详细信息。
从 NDB 复制到非事务性存储引擎。 当从 NDB
复制到非事务性存储引擎,如 MyISAM
时,您可能会遇到不必要的重复键错误,当复制 INSERT ... ON DUPLICATE KEY UPDATE
语句时。您可以使用 --ndb-log-update-as-write=0
,强制更新被记录为写入,而不是更新。
复制和二进制日志过滤规则与 NDB 集群之间的复制。 如果您使用任何选项 --replicate-do-*
、--replicate-ignore-*
、--binlog-do-db
或 --binlog-ignore-db
来过滤正在复制的数据库或表格,您必须小心不要阻止 mysql.ndb_apply_status
的复制或二进制日志记录,这是 NDB 集群之间的复制所需的。在 particular,您必须牢记以下几点:
-
使用
--replicate-do-db=
(且不使用其他db_name
--replicate-do-*
或--replicate-ignore-*
选项)意味着 仅 复制数据库db_name
中的表格。在这种情况下,您也应该使用--replicate-do-db=mysql
、--binlog-do-db=mysql
或--replicate-do-table=mysql.ndb_apply_status
,以确保mysql.ndb_apply_status
在副本上被填充。使用
--binlog-do-db=
(且不使用其他db_name
--binlog-do-db
选项)意味着 仅 将数据库db_name
中的表格更改写入二进制日志。在这种情况下,您也应该使用--replicate-do-db=mysql
、--binlog-do-db=mysql
或--replicate-do-table=mysql.ndb_apply_status
,以确保mysql.ndb_apply_status
在副本上被填充。 -
使用
--replicate-ignore-db=mysql
意味着不复制mysql
数据库中的任何表格。在这种情况下,您也应该使用--replicate-do-table=mysql.ndb_apply_status
,以确保mysql.ndb_apply_status
被复制。使用
--binlog-ignore-db=mysql
意味着不将mysql
数据库中的任何表格更改写入二进制日志。在这种情况下,您也应该使用--replicate-do-table=mysql.ndb_apply_status
,以确保mysql.ndb_apply_status
被复制。
您还应该记住,每个复制规则都需要以下几点:
-
它自己的
--replicate-do-*
或--replicate-ignore-*
选项,并且多个规则不能在单个复制过滤选项中表达。有关这些规则的信息,请参阅 第 19.1.6 节,“复制和二进制日志记录选项和变量”。 -
它自己的
--binlog-do-db
或--binlog-ignore-db
选项,并且多个规则不能在单个二进制日志过滤选项中表达。有关这些规则的信息,请参阅 第 7.4.4 节,“二进制日志”。
如果您正在将 NDB 集群复制到使用其他存储引擎(而不是 NDB
)的副本上,那么前面提到的考虑可能不适用,如本节其他地方所讨论的那样。
NDB 集群复制和 IPv6。 在 NDB 8.3 中,所有类型的 NDB 集群节点都支持 IPv6,包括管理节点、数据节点和 API 或 SQL 节点。
在某些以前的版本中,NDB
无法在没有操作系统 IPv6 支持的情况下成功启动,即使没有使用 IPv6 地址。这不是 NDB 8.1 的问题,在这里您可以禁用 Linux 内核中的 IPv6 支持,如果您不打算使用 IPv6 地址来连接任何 NDB 集群节点。
属性升级和降级。 NDB 集群复制包括对属性升级和降级的支持。后者的实现区分了损失和非损失类型转换,并且可以通过设置系统变量 replica_type_conversions
的全局值来控制副本上的使用。
有关 NDB 集群中的属性升级和降级的更多信息,请参阅 基于行的复制:属性升级和降级。
NDB
,与 InnoDB
或 MyISAM
不同, 不会将虚拟列的更改写入二进制日志;然而,这对 NDB 集群复制或 NDB 和其他存储引擎之间的复制没有不良影响。存储生成列的更改将被记录。