21.6.4 NDB 群集复制架构和 table

NDB 群集中的复制使用每个 MySQL Server 实例mysql数据库中的许多专用 table,这些实例在要复制的群集和副本中均充当 SQL 节点。不管副本是单个服务器还是群集,都是如此。这些 table 是在 MySQL 安装过程中创建的,其中包括一个用于存储二进制日志的索引数据的 table。由于ndb_binlog_indextable 对于每个 MySQL 服务器来说都是本地的,并且不参与集群,因此它使用InnoDB存储引擎。这意味着必须在参与源群集的每个mysqld上分别创建它。 (二进制日志本身包含要复制的集群中所有 MySQL 服务器的更新.)此 table 定义如下:

CREATE TABLE `ndb_binlog_index` (
    `Position` BIGINT(20) UNSIGNED NOT NULL,
    `File` VARCHAR(255) NOT NULL,
    `epoch` BIGINT(20) UNSIGNED NOT NULL,
    `inserts` INT(10) UNSIGNED NOT NULL,
    `updates` INT(10) UNSIGNED NOT NULL,
    `deletes` INT(10) UNSIGNED NOT NULL,
    `schemaops` INT(10) UNSIGNED NOT NULL,
    `orig_server_id` INT(10) UNSIGNED NOT NULL,
    `orig_epoch` BIGINT(20) UNSIGNED NOT NULL,
    `gci` INT(10) UNSIGNED NOT NULL,
    `next_position` bigint(20) unsigned NOT NULL,
    `next_file` varchar(255) NOT NULL,
    PRIMARY KEY (`epoch`,`orig_server_id`,`orig_epoch`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Note

在 NDB 7.5.2 之前,此 table 始终使用MyISAM存储引擎。如果要从早期版本进行升级,则可以在启动服务器后将mysql_upgrade--force--upgrade-system-tables选项一起使用。)系统 table 升级导致对该 table 执行ALTER TABLE ... ENGINE = INNODB语句。为了向后兼容,continue 支持对该 table 使用MyISAM存储引擎。

ndb_binlog_index转换为InnoDB后可能需要额外的磁盘空间。如果这成为问题,则可以通过为此 table 使用InnoDBtable 空间,将其ROW_FORMAT更改为COMPRESSED或同时使用两者来节省空间。有关更多信息,请参见第 13.1.19 节“ CREATE TABLESPACE 语句”第 13.1.18 节“ CREATE TABLE 语句”以及第 14.6.3 节“table 空间”

ndb_binlog_indextable 的大小取决于每个二进制日志文件的纪元数和二进制日志文件的数。每个二进制日志文件的纪元数通常取决于每个纪元生成的二进制日志数和二进制日志文件的大小,纪元越小,每个文件的纪元就越多。您应该意识到,即使--ndb-log-empty-epochs选项为OFF,空的纪元也会在ndb_binlog_indextable 中产生插入,这意味着每个文件的条目数取决于文件的使用时间。这种关系可以用下面的公式 table 示:

[number of epochs per file] = [time spent per file] / TimeBetweenEpochs

繁忙的 NDB 群集会定期写入二进制日志,大概比安静的二进制文件旋转速度更快。这意味着具有--ndb-log-empty-epochs=ON的“安静” NDB 群集实际上每个文件中具有ndb_binlog_index行的数量比具有大量活动的 NDB 群集要多得多。

当使用--ndb-log-orig选项启动mysqld时,orig_server_idorig_epoch列分别存储事件发生所在的服务器的 ID 和事件发生在原始服务器上的时期,这在 NDB 群集复制设置中很有用雇用多个来源。 SELECT语句用于在多源设置(请参见第 21.6.10 节“ NDB 群集复制:双向复制和循环复制”)中找到与副本上应用的最高纪元最接近的二进制日志位置,该语句使用了这两列,但未构建索引。尝试进行故障转移时,这可能会导致性能问题,因为查询必须执行 table 扫描,尤其是当源使用--ndb-log-empty-epochs=ON运行时。您可以通过向这些列添加索引来缩短多源故障转移时间,如下所示:

ALTER TABLE mysql.ndb_binlog_index
    ADD INDEX orig_lookup USING BTREE (orig_server_id, orig_epoch);

从单个源复制到单个副本时,添加此索引没有任何好处,因为在这种情况下,用于获取二进制日志位置的查询不使用orig_server_idorig_epoch

有关使用next_positionnext_file列的更多信息,请参见第 21.6.8 节“使用 NDB 群集复制实现故障转移”

下图显示了 NDB 群集复制源服务器,其二进制日志注入程序线程和mysql.ndb_binlog_indextable 之间的关系。

图 21.47 复制源群集

大多数概念在周围的文本中进行了描述。这个复杂的图像具有三个主要区域。顶部区域分为三个部分:MySQL 服务器(mysqld),NDBCLUSTERtable 处理程序和 Mutex。连接线程连接这些线程,接收器线程和注入器线程连接 NDBCLUSTERtable 处理程序和互斥锁。底部区域显示四个数据节点(ndbd)。它们都产生由指向接收器线程的箭头 table 示的事件,并且接收器线程也指向连接和注入器线程。一个节点向互斥区发送和接收。代 table 喷油器螺纹的箭头指向二进制日志以及 ndb_binlog_indextable,该 table 在周围的文本中进行了描述。

另一个名为ndb_apply_status的 table 用于记录从源复制到副本的操作的记录。与ndb_binlog_index的情况不同,此 table 中的数据并非特定于(副本)集群中的任何一个 SQL 节点,因此ndb_apply_status可以使用NDBCLUSTER存储引擎,如下所示:

CREATE TABLE `ndb_apply_status` (
    `server_id`   INT(10) UNSIGNED NOT NULL,
    `epoch`       BIGINT(20) UNSIGNED NOT NULL,
    `log_name`    VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
    `start_pos`   BIGINT(20) UNSIGNED NOT NULL,
    `end_pos`     BIGINT(20) UNSIGNED NOT NULL,
    PRIMARY KEY (`server_id`) USING HASH
) ENGINE=NDBCLUSTER   DEFAULT CHARSET=latin1;

ndb_apply_statustable 仅填充在副本上,这意味着,在源上,此 table 从不包含任何行。因此,无需在此向ndb_apply_status分配任何DataMemoryIndexMemory

由于此 table 是从源上的数据中填充的,因此应允许对其进行复制;任何不经意间阻止副本更新ndb_apply_status或阻止源写入二进制日志的复制过滤或二进制日志过滤规则,都可能阻止群集之间的复制正常运行。有关由此类过滤规则引起的潜在问题的更多信息,请参见在 NDB 群集之间进行复制的复制和二进制日志过滤规则

ndb_binlog_indexndb_apply_statustable 是在mysql数据库中创建的,因为用户不应明确地复制它们。通常无需用户干预即可创建或维护这两个 table,因为这两个 table 均由NDB二进制日志(binlog)注入程序线程维护。这样可以将源mysqld进程更新为由NDB存储引擎执行的更改。 NDB binlog 注入程序线程直接从NDB存储引擎接收事件。 NDB注入程序负责捕获集群中的所有数据事件,并确保将所有更改,插入或删除数据的事件记录在ndb_binlog_indextable 中。副本 I/O 线程将事件从源的二进制日志传输到副本的中继日志。

即使ndb_binlog_indexndb_apply_status是自动创建和维护的,还是建议检查这些 table 的存在和完整性,以此作为准备复制 NDB 群集的第一步。通过直接在源上查询mysql.ndb_binlog_indextable,可以查看二进制日志中记录的事件数据。也可以使用源 SQL 节点或副本 SQL 节点上的显示 BINLOG 事件语句来完成此操作。 (请参阅第 13.7.5.2 节“ SHOW BINLOG 事件声明”。)

您还可以从显示引擎 NDB 状态的输出中获取有用的信息。

Note

NDBtable 上执行模式更改时,应用程序应等到发出该语句的 MySQLClient 端 Connecting 返回ALTER TABLE语句后,再尝试使用 table 的更新定义。

如果副本上不存在ndb_apply_statustable,则ndb_restore重新创建它。

NDB 群集复制的冲突解决方案要求存在另一个mysql.ndb_replicationtable。当前,该 table 必须手动创建。有关如何执行此操作的信息,请参见第 21.6.11 节“ NDB 群集复制冲突解决”