NDB Cluster 中的复制在每个 MySQL Server 实例上使用数据库中的许多专用表mysql
作为正在复制的集群和副本中的 SQL 节点。无论副本是单个服务器还是集群,都是如此。
ndb_binlog_index
和
ndb_apply_status
表是在
mysql
数据库中创建
的。用户不应明确复制它们。通常不需要用户干预来创建或维护这些表中的任何一个,因为它们都由NDB
二进制日志 (binlog) 注入器线程维护。这使源
mysqldNDB
进程更新为存储引擎执行的更改。二进制日志注入器
线程直接从
存储引擎接收事件。注入器负责捕获集群内的所有数据事件,并确保所有更改、插入或删除数据的事件都记录在
NDB
NDB
NDB
ndb_binlog_index
桌子。副本 I/O 线程将事件从源的二进制日志传输到副本的中继日志。
该ndb_replication
表必须手动创建。用户可以更新此表以按数据库或表执行过滤。有关详细信息,请参阅
ndb_replication 表。ndb_replication
也用于 NDB Replication 冲突检测和解决,用于冲突解决控制;请参阅
冲突解决控制。
尽管ndb_binlog_index
和
ndb_apply_status
是自动创建和维护的,但建议检查这些表的存在性和完整性,作为准备 NDB Cluster 进行复制的初始步骤。mysql.ndb_binlog_index
可以通过直接在源上查询表来查看二进制日志中记录的事件数据
。这也可以使用
SHOW BINLOG EVENTS
源 SQL 节点或副本 SQL 节点上的语句来完成。(参见
第 13.7.5.2 节,“SHOW BINLOG EVENTS 语句”。)
您还可以从 的输出中获取有用的信息
SHOW ENGINE NDB
STATUS
。
在
NDB
表上执行模式更改时,应用程序应等到ALTER TABLE
语句在发出该语句的 MySQL 客户端连接中返回,然后再尝试使用表的更新定义。
ndb_apply_status
用于记录已从源复制到副本的操作。如果该ndb_apply_status
表在副本上不存在,ndb_restore
会重新创建它。
与 的情况不同ndb_binlog_index
,此表中的数据不特定于(副本)集群中的任何一个 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_status
表仅在副本上填充,这意味着在源上,该表从不包含任何行;因此,没有必要在那里分配任何
DataMemory
东西
ndb_apply_status
。
因为这个表是从来自源的数据填充的,所以应该允许复制;任何无意中阻止副本更新
ndb_apply_status
或阻止源写入二进制日志的复制过滤或二进制日志过滤规则可能会阻止集群之间的复制正常运行。有关此类过滤规则引起的潜在问题的更多信息,请参阅
复制和二进制日志过滤规则以及 NDB 集群之间的复制。
0
此表的epoch
列中的 表示源自除 之外的存储引擎的事务NDB
。
NDB Cluster Replication 使用该
ndb_binlog_index
表来存储二进制日志的索引数据。由于这张表是每个MySQL服务器本地的,不参与集群,所以使用
InnoDB
存储引擎。这意味着它必须在
参与源集群的每个mysqld上单独创建。(二进制日志本身包含来自集群中所有 MySQL 服务器的更新。)该表定义如下:
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;
在 NDB 7.5.2 之前,此表始终使用
MyISAM
存储引擎。如果您是从较早的版本升级,则可以在启动服务器后使用
带有
和
选项的mysql_upgrade
。)系统表升级会导致对该表执行一条语句。为了向后兼容,继续支持使用此表
的存储引擎。--force
--upgrade-system-tables
ALTER
TABLE ... ENGINE=INNODB
MyISAM
ndb_binlog_index
转换为InnoDB
. 如果这成为一个问题,您可以通过InnoDB
为此表使用一个表空间、将其更改ROW_FORMAT
为
COMPRESSED
或两者来节省空间。有关详细信息,请参阅第 13.1.19 节,“CREATE TABLESPACE 语句”和
第 13.1.18 节,“CREATE TABLE 语句”,以及
第 14.6.3 节,“表空间”。
表的大小ndb_binlog_index
取决于每个二进制日志文件的纪元数和二进制日志文件的数量。每个二进制日志文件的纪元数通常取决于每个纪元生成的二进制日志量和二进制日志文件的大小,较小的纪元会导致每个文件的纪元数较多。您应该知道
ndb_binlog_index
,即使
--ndb-log-empty-epochs
选项为
OFF
,空时期也会对表产生插入,这意味着每个文件的条目数取决于文件使用的时间长度;这种关系可以用此处显示的公式表示:
[number of epochs per file] = [time spent per file] / TimeBetweenEpochs
繁忙的 NDB Cluster 定期写入二进制日志,并且可能比安静的更快地旋转二进制日志文件。这意味着一个“安静”的NDB Cluster
--ndb-log-empty-epochs=ON
实际上
ndb_binlog_index
每个文件的行数比一个有大量活动的 NDB Cluster 多得多。
当mysqld以
--ndb-log-orig
选项启动时,
orig_server_id
和
orig_epoch
列分别存储事件发起的服务器的 ID 和事件在发起服务器上发生的纪元,这在使用多个源的 NDB Cluster 复制设置中很有用. 该SELECT
语句用于在多源设置中找到最接近副本上最高应用纪元的二进制日志位置(请参阅
第 21.7.10 节,“NDB 集群复制:双向和循环复制”) 使用这两列,它们没有索引。这可能会在尝试故障转移时导致性能问题,因为查询必须执行表扫描,尤其是当源已使用
--ndb-log-empty-epochs=ON
. 您可以通过向这些列添加索引来缩短多源故障转移时间,如下所示:
ALTER TABLE mysql.ndb_binlog_index
ADD INDEX orig_lookup USING BTREE (orig_server_id, orig_epoch);
当从单个源复制到单个副本时,添加此索引没有任何好处,因为在这种情况下用于获取二进制日志位置的查询不使用
orig_server_id
or
orig_epoch
。
有关使用和
列
的更多信息,
请参阅第 21.7.8 节,“使用 NDB Cluster 复制实现故障转移” 。next_position
next_file
下图显示了 NDB Cluster 复制源服务器、其二进制日志注入器线程和mysql.ndb_binlog_index
表的关系。
该ndb_replication
表用于控制二进制日志记录和冲突解决,并以每个表为基础进行操作。此表中的每一行对应一个正在复制的表,确定如何记录对表的更改,如果指定了冲突解决函数,则确定如何解决该表的冲突。
与表不同ndb_apply_status
,
ndb_replication
该
ndb_replication
表必须手动创建,使用此处显示的 SQL 语句:
CREATE TABLE mysql.ndb_replication (
db VARBINARY(63),
table_name VARBINARY(63),
server_id INT UNSIGNED,
binlog_type INT UNSIGNED,
conflict_fn VARBINARY(128),
PRIMARY KEY USING HASH (db, table_name, server_id)
) ENGINE=NDB
PARTITION BY KEY(db,table_name);
此处列出了此表的列,并附有说明:
db
柱子包含要复制的表的数据库的名称。
您可以使用其中一个或两个通配符 作为数据库名称的一部分
_
。%
(请参阅 本节后面的 使用通配符匹配。)table_name
柱子要复制的表的名称。
_
表名可以包含通配符和 中的一个或两个%
。请参阅 本节后面的 使用通配符匹配。server_id
柱子表所在的 MySQL 实例(SQL 节点)的唯一服务器 ID。
0
此列中的 充当通配符,相当于%
, 并匹配任何服务器 ID。(请参阅本节后面的 使用通配符匹配。)binlog_type
柱子要使用的二进制日志记录类型。有关值和说明,请参阅文本。
conflict_fn
柱子要应用的冲突解决函数;NDB$OLD()、 NDB$MAX()、 NDB$MAX_DELETE_WIN()、 NDB$EPOCH()、 NDB$EPOCH_TRANS()、 NDB$EPOCH2()、 NDB$EPOCH2_TRANS ( ) 之一;
NULL
表示该表不使用冲突解决。有关这些功能及其在 NDB 复制冲突解决中的用途的更多信息, 请参阅冲突解决功能。
一些冲突解决函数 (
NDB$OLD()
,NDB$EPOCH()
,NDB$EPOCH_TRANS()
) 需要使用一个或多个用户创建的异常表。请参阅 冲突解决例外表。
要使用 NDB 复制启用冲突解决,有必要使用有关应解决冲突的一个或多个 SQL 节点的控制信息创建并填充此表。根据要采用的冲突解决类型和方法,这可能是源服务器、副本服务器或两者都是服务器。在一个简单的源副本设置中,数据也可以在副本上本地更改,这通常是副本。在更复杂的复制方案中,例如双向复制,这通常是所有涉及的源。有关更多信息,请参阅 第 21.7.11 节,“NDB Cluster 复制冲突解决”。
该ndb_replication
表允许在冲突解决范围之外对二进制日志记录进行表级控制,在这种情况下conflict_fn
指定为NULL
,而其余列值用于控制与通配符表达式匹配的给定表或一组表的二进制日志记录。通过为该binlog_type
列设置适当的值,您可以使给定表或表的日志记录使用所需的二进制日志格式,或者完全禁用二进制日志记录。此列的可能值及其值和说明如下表所示:
表 21.64 binlog_type 值,以及值和描述
价值 | 描述 |
---|---|
0 | 使用服务器默认值 |
1个 | 不要将此表记录到二进制日志中(效果与 相同
sql_log_bin = 0 ,但仅适用于一个或多个指定的表) |
2个 | 仅记录更新的属性;将这些记录为WRITE_ROW
事件 |
3个 | 记录整行,即使没有更新(MySQL 服务器默认行为) |
6个 | 使用更新的属性,即使值未更改 |
7 | 记录整行,即使没有更改任何值;将更新记录为
UPDATE_ROW 事件 |
8个 | 记录更新为UPDATE_ROW ;仅记录前映像中的主键列,仅记录后映像中的更新列(效果与 相同
--ndb-log-update-minimal ,但仅适用于一个或多个指定表) |
9 | 记录更新为UPDATE_ROW ;仅记录前映像中的主键列,以及后映像中除主键列以外的所有列 |
binlog_type
值 4 和 5 未使用,因此在刚刚显示的表格以及下一个表格中省略了。
几个值等效于mysqld日志记录选项、
和
binlog_type
的各种组合,如下表所示:
--ndb-log-updated-only
--ndb-log-update-as-write
--ndb-log-update-minimal
表 21.65 binlog_type 值与 NDB 日志记录选项的等效组合
价值 | --ndb-log-updated-only 价值 |
--ndb-log-update-as-write 价值 |
--ndb-log-update-minimal 价值 |
---|---|---|---|
0 | -- | -- | -- |
1个 | -- | -- | -- |
2个 | 上 | 上 | 离开 |
3个 | 离开 | 上 | 离开 |
6个 | 上 | 离开 | 离开 |
7 | 离开 | 离开 | 离开 |
8个 | 上 | 离开 | 上 |
9 | 离开 | 离开 | 上 |
ndb_replication
通过使用适当
db
的table_name
、 和
binlog_type
列值
将行插入表中,可以将二进制日志记录设置为不同表的不同格式
。设置二进制日志记录格式时应使用上表中显示的内部整数值。以下两个语句将二进制日志记录设置为记录表的完整行(值 3)test.a
,以及仅记录表的更新(值 2)test.b
:
# Table test.a: Log full rows
INSERT INTO mysql.ndb_replication VALUES("test", "a", 0, 3, NULL);
# Table test.b: log updates only
INSERT INTO mysql.ndb_replication VALUES("test", "b", 0, 2, NULL);
要禁用一个或多个表的日志记录,请使用 1 binlog_type
,如下所示:
# Disable binary logging for table test.t1
INSERT INTO mysql.ndb_replication VALUES("test", "t1", 0, 1, NULL);
# Disable binary logging for any table in 'test' whose name begins with 't'
INSERT INTO mysql.ndb_replication VALUES("test", "t%", 0, 1, NULL);
禁用给定表的日志记录等同于设置
sql_log_bin = 0
,只是它单独应用于一个或多个表。如果 SQL 节点未对给定表执行二进制日志记录,则不会向其发送这些表的行更改事件。这意味着它没有接收所有更改并丢弃一些更改,而是没有订阅这些更改。
出于多种原因,禁用日志记录可能很有用,包括此处列出的原因:
不通过网络发送更改通常可以节省带宽、缓冲和 CPU 资源。
不记录对更新非常频繁但值不大的表的更改非常适合临时数据(例如会话数据),这些数据在集群完全失败的情况下可能相对不重要。
使用会话变量(或
sql_log_bin
)和应用程序代码,还可以记录(或不记录)某些 SQL 语句或 SQL 语句类型;例如,在某些情况下可能不希望在一个或多个表上记录 DDL 语句。出于性能原因,可以将复制流拆分为两个(或更多)二进制日志,需要将不同的数据库复制到不同的地方,为不同的数据库使用不同的二进制日志记录类型,等等。
与通配符匹配。
为了不需要
ndb_replication
在复制设置中为数据库、表和 SQL 节点的每个组合在表中插入一行,NDB
支持在此表的db
、
table_name
和
server_id
列上进行通配符匹配。分别使用的数据库和表名,db
并且
table_name
可以包含以下一个或两个通配符:
_
(下划线字符):匹配零个或多个字符%
(百分号):匹配单个字符
(这些通配符与 MySQL
LIKE
运算符所支持的相同。)
该server_id
列支持
0
作为等效于
_
(匹配任何内容)的通配符。这用于前面显示的示例中。
表中的给定行ndb_replication
可以使用通配符来匹配任何数据库名称、表名称和服务器 ID 的任意组合。如果表中有多个潜在匹配,则选择最佳匹配,根据此处显示的表,其中W表示通配符匹配,E表示完全匹配,并且Quality列中的值越大,匹配越好:
表 21.66 mysql.ndb_replication 表中列的通配符和精确匹配的不同组合的权重
db |
table_name |
server_id |
质量 |
---|---|---|---|
W | W | W | 1个 |
W | W | 乙 | 2个 |
W | 乙 | W | 3个 |
W | 乙 | 乙 | 4个 |
乙 | W | W | 5个 |
乙 | W | 乙 | 6个 |
乙 | 乙 | W | 7 |
乙 | 乙 | 乙 | 8个 |
因此,数据库名称、表名称和服务器 ID 的完全匹配被认为是最好的(最强的),而最弱的(最差的)匹配是所有三列的通配符匹配。选择要应用的规则时,只考虑比赛的强度;行在表中出现的顺序对该确定没有影响。
记录完整或部分行。
有两种记录行的基本方法,由
mysqld--ndb-log-updated-only
的选项设置决定:
记录完整的行(选项设置为
ON
)仅记录已更新的列数据,即已设置值的列数据,而不管该值是否实际更改。这是默认行为(选项设置为
OFF
)。
通常只记录更新的列就足够了——而且效率更高;但是,如果您需要记录完整的行,您可以通过设置
--ndb-log-updated-only
为
0
或来实现OFF
。
将更改的数据记录为更新。
MySQL 服务器
--ndb-log-update-as-write
选项的设置决定了是否使用“之前”图像执行日志记录。
因为更新和删除操作的冲突解决是在 MySQL 服务器的更新处理程序中完成的,所以有必要控制复制源执行的日志记录,以便更新是更新而不是写入;也就是说,更新被视为对现有行的更改而不是写入新行,即使这些更新替换了现有行。
该选项默认开启;换句话说,更新被视为写入。也就是说,更新默认情况下作为
write_row
事件写入二进制日志中,而不是作为update_row
事件。
要禁用该选项,请
使用
或
启动源mysqld。从 NDB 表复制到使用不同存储引擎的表时,您必须这样做;有关详细信息,请参阅
从 NDB 到其他存储引擎的复制和
从 NDB 到非事务性存储引擎的复制。
--ndb-log-update-as-write=0
--ndb-log-update-as-write=OFF