NDB 集群磁盘数据存储使用以下对象实现:
-
表空间:充当其他磁盘数据对象的容器。表空间包含一个或多个数据文件和一个或多个撤销日志文件组。
-
数据文件:存储列数据。数据文件直接分配给表空间。
-
撤销日志文件:包含撤销事务所需的撤销信息。分配给撤销日志文件组。
-
日志文件组:包含一个或多个撤销日志文件。分配给表空间。
撤销日志文件和数据文件是每个数据节点文件系统中的实际文件;默认情况下,它们位于 ndb_
中的 node_id
_fsDataDir
指定的 NDB 集群 config.ini
文件中,其中 node_id
是数据节点的节点 ID。可以通过指定绝对或相对路径作为文件名的一部分来将它们放在其他位置。创建这些文件的语句将在本节后面显示。
撤销日志文件仅用于磁盘数据表,不用于仅存储在内存中的 NDB
表。
NDB 集群表空间和日志文件组不是作为文件实现的。
尽管不是所有磁盘数据对象都是文件,但它们都共享同一个命名空间。这意味着 每个磁盘数据对象 都必须具有唯一的名称(而不仅仅是每个磁盘数据对象类型)。例如,您不能同时拥有一个名为 dd1
的表空间和一个名为 dd1
的日志文件组。
假设您已经设置了 NDB 集群,包括所有节点(包括管理节点和 SQL 节点),那么创建 NDB 集群磁盘表的基本步骤如下:
-
创建一个日志文件组,并将一个或多个撤销日志文件分配给它(撤销日志文件有时也称为 undofile)。
-
创建一个表空间;将日志文件组和一个或多个数据文件分配给表空间。
-
创建一个使用该表空间进行数据存储的磁盘数据表。
每个任务都可以使用 mysql 客户端或其他 MySQL 客户端应用程序中的 SQL 语句来完成,如下面的示例所示。
-
我们创建了一个名为
lg_1
的日志文件组,使用CREATE LOGFILE GROUP
。该日志文件组由两个撤销日志文件组成,名为undo_1.log
和undo_2.log
,初始大小分别为 16 MB 和 12 MB。(撤销日志文件的默认初始大小为 128 MB。)可选地,您也可以指定撤销缓冲区的大小,或者允许其采用默认值 8 MB。在这个示例中,我们将撤销缓冲区的大小设置为 2 MB。日志文件组必须创建一个撤销日志文件;因此,我们将undo_1.log
添加到lg_1
中的这个CREATE LOGFILE GROUP
语句中:CREATE LOGFILE GROUP lg_1 ADD UNDOFILE 'undo_1.log' INITIAL_SIZE 16M UNDO_BUFFER_SIZE 2M ENGINE NDBCLUSTER;
要将
undo_2.log
添加到日志文件组中,请使用以下ALTER LOGFILE GROUP
语句:ALTER LOGFILE GROUP lg_1 ADD UNDOFILE 'undo_2.log' INITIAL_SIZE 12M ENGINE NDBCLUSTER;
一些要注意的项目:
-
这里使用的
.log
文件扩展名不是必需的。我们只是为了使日志文件易于识别。 -
每个
CREATE LOGFILE GROUP
和ALTER LOGFILE GROUP
语句都必须包含一个ENGINE
选项。该选项的唯一允许值是NDBCLUSTER
和NDB
。Important在任何给定的 NDB 集群中,至多只能存在一个日志文件组。
-
当您使用
ADD UNDOFILE '
将撤销日志文件添加到日志文件组时,一个名为filename
'filename
的文件将在每个数据节点的ndb_
目录中创建,其中node_id
_fsnode_id
是数据节点的节点 ID。每个撤销日志文件的大小是 SQL 语句中指定的大小。例如,如果 NDB 集群有 4 个数据节点,那么ALTER LOGFILE GROUP
语句将创建 4 个撤销日志文件,每个文件名为undo_2.log
,每个文件大小为 12 MB。 -
UNDO_BUFFER_SIZE
受限于系统可用内存的数量。 -
请参阅 第 15.1.16 节,“CREATE LOGFILE GROUP 语句” 和 第 15.1.6 节,“ALTER LOGFILE GROUP 语句”,以获取更多关于这些语句的信息。
-
-
现在我们可以创建一个表空间——一个抽象的容器,用于存储 Disk Data 表的数据。表空间与特定的日志文件组关联;创建新表空间时,必须指定其使用的日志文件组。您还必须指定至少一个数据文件;可以在表空间创建后添加更多数据文件到表空间中(参见本节后面的示例)。也可以从表空间中删除数据文件(参见本节后面的示例)。
假设我们想创建一个名为
ts_1
的表空间,它使用lg_1
作为其日志文件组。我们想让表空间包含两个数据文件,名为data_1.dat
和data_2.dat
,初始大小分别为 32 MB 和 48 MB。(默认值为INITIAL_SIZE
是 128 MB。)我们可以使用两个 SQL 语句来实现,如下所示:CREATE TABLESPACE ts_1 ADD DATAFILE 'data_1.dat' USE LOGFILE GROUP lg_1 INITIAL_SIZE 32M ENGINE NDBCLUSTER; ALTER TABLESPACE ts_1 ADD DATAFILE 'data_2.dat' INITIAL_SIZE 48M;
该
CREATE TABLESPACE
语句创建了一个名为ts_1
的表空间,具有数据文件data_1.dat
,并将ts_1
与日志文件组lg_1
关联。该ALTER TABLESPACE
语句添加了第二个数据文件(data_2.dat
)。一些需要注意的项目:
-
与撤销日志文件使用的
.log
文件扩展名类似,数据文件使用的.dat
文件扩展名也没有特殊意义,只是为了便于识别。 -
当您使用
ADD DATAFILE '
将数据文件添加到表空间时,一个名为filename
'filename
的文件将在每个数据节点的ndb_
目录中创建,其中node_id
_fsnode_id
是数据节点的节点 ID。每个数据文件的大小是 SQL 语句中指定的大小。例如,如果 NDB 集群有 4 个数据节点,那么ALTER TABLESPACE
语句将创建 4 个数据文件,每个文件名为data_2.dat
,每个文件大小为 48 MB。 -
NDB
保留每个表空间的 4% 用于数据节点重新启动时使用。这些空间不可用于存储数据。 -
CREATE TABLESPACE
语句必须包含一个ENGINE
子句;只有使用相同存储引擎的表可以在表空间中创建。对于ALTER TABLESPACE
,ENGINE
子句是可接受的,但已弃用,并将在未来版本中删除。对于NDB
表空间,唯一允许的值为NDBCLUSTER
和NDB
。 -
表空间中的 extent 分配是以循环方式在所有数据文件中进行的。
-
有关
CREATE TABLESPACE
和ALTER TABLESPACE
语句的更多信息,请参阅 第 15.1.21 节,“CREATE TABLESPACE 语句” 和 第 15.1.10 节,“ALTER TABLESPACE 语句”。
-
-
现在可以创建一个表,其中未索引的列存储在磁盘上使用文件在表空间
ts_1
中:CREATE TABLE dt_1 ( member_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, last_name VARCHAR(50) NOT NULL, first_name VARCHAR(50) NOT NULL, dob DATE NOT NULL, joined DATE NOT NULL, INDEX(last_name, first_name) ) TABLESPACE ts_1 STORAGE DISK ENGINE NDBCLUSTER;
TABLESPACE ts_1 STORAGE DISK
告诉NDB
存储引擎使用表空间ts_1
进行磁盘数据存储。一旦表
ts_1
创建完成,如上所示,您可以在其上执行INSERT
、SELECT
、UPDATE
和DELETE
语句,就像对任何其他 MySQL 表一样。还可以使用
STORAGE
子句指定个别列是否存储在磁盘上或内存中,作为CREATE TABLE
或ALTER TABLE
语句的一部分。STORAGE DISK
导致列存储在磁盘上,而STORAGE MEMORY
导致在内存中存储。请参阅 第 15.1.20 节,“CREATE TABLE 语句”,以获取更多信息。
您可以通过查询 INFORMATION_SCHEMA
数据库中的 FILES
表来获取刚刚创建的 NDB 磁盘数据文件和撤销日志文件的信息,如下所示:
mysql> SELECT
FILE_NAME AS File, FILE_TYPE AS Type,
TABLESPACE_NAME AS Tablespace, TABLE_NAME AS Name,
LOGFILE_GROUP_NAME AS 'File group',
FREE_EXTENTS AS Free, TOTAL_EXTENTS AS Total
FROM INFORMATION_SCHEMA.FILES
WHERE ENGINE='ndbcluster';
+--------------+----------+------------+------+------------+------+---------+
| File | Type | Tablespace | Name | File group | Free | Total |
+--------------+----------+------------+------+------------+------+---------+
| ./undo_1.log | UNDO LOG | lg_1 | NULL | lg_1 | 0 | 4194304 |
| ./undo_2.log | UNDO LOG | lg_1 | NULL | lg_1 | 0 | 3145728 |
| ./data_1.dat | DATAFILE | ts_1 | NULL | lg_1 | 32 | 32 |
| ./data_2.dat | DATAFILE | ts_1 | NULL | lg_1 | 48 | 48 |
+--------------+----------+------------+------+------------+------+---------+
4 rows in set (0.00 sec)
有关更多信息和示例,请参阅 第 28.3.15 节,“The INFORMATION_SCHEMA FILES 表”。
隐式存储在磁盘上的列索引。 对于上面示例中定义的表 dt_1
,只有 dob
和 joined
列存储在磁盘上。这是因为 id
、last_name
和 first_name
列有索引,因此这些列的数据存储在 RAM 中。只有非索引列可以存储在磁盘上;索引和索引列数据继续存储在内存中。这是您在设计 Disk Data 表时需要牢记的权衡。
您不能将索引添加到已经明确声明为 STORAGE DISK
的列中,除非首先将其存储类型更改为 MEMORY
;否则尝试这样做将失败并出现错误。隐式使用磁盘存储的列可以索引;当这样做时,该列的存储类型将自动更改为 MEMORY
。通过 隐式,我们指的是没有明确声明存储类型的列,但继承自父表的存储类型。在以下 CREATE TABLE 语句中(使用之前定义的表空间 ts_1
),列 c2
和 c3
隐式使用磁盘存储:
mysql> CREATE TABLE ti (
-> c1 INT PRIMARY KEY,
-> c2 INT,
-> c3 INT,
-> c4 INT
-> )
-> STORAGE DISK
-> TABLESPACE ts_1
-> ENGINE NDBCLUSTER;
Query OK, 0 rows affected (1.31 sec)
因为 c2
、c3
和 c4
本身没有声明 STORAGE DISK
,因此可以对它们进行索引。这里,我们使用 CREATE INDEX
和 ALTER TABLE
分别对 c2
和 c3
添加索引:
mysql> CREATE INDEX i1 ON ti(c2);
Query OK, 0 rows affected (2.72 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> ALTER TABLE ti ADD INDEX i2(c3);
Query OK, 0 rows affected (0.92 sec)
Records: 0 Duplicates: 0 Warnings: 0
SHOW CREATE TABLE
确认了索引的添加。
mysql> SHOW CREATE TABLE ti\G
*************************** 1. row ***************************
Table: ti
Create Table: CREATE TABLE `ti` (
`c1` int(11) NOT NULL,
`c2` int(11) DEFAULT NULL,
`c3` int(11) DEFAULT NULL,
`c4` int(11) DEFAULT NULL,
PRIMARY KEY (`c1`),
KEY `i1` (`c2`),
KEY `i2` (`c3`)
) /*!50100 TABLESPACE `ts_1` STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
您可以使用 ndb_desc 查看索引列(强调文本)现在使用内存存储,而不是磁盘存储:
$> ./ndb_desc -d test t1
-- t1 --
Version: 33554433
Fragment type: HashMapPartition
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 4
Number of primary keys: 1
Length of frm data: 317
Max Rows: 0
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
PartitionCount: 4
FragmentCount: 4
PartitionBalance: FOR_RP_BY_LDM
ExtraRowGciBits: 0
ExtraRowAuthorBits: 0
TableStatus: Retrieved
Table options:
HashMap: DEFAULT-HASHMAP-3840-4
-- Attributes --
c1 Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
c2 Int NULL AT=FIXED ST=MEMORY
c3 Int NULL AT=FIXED ST=MEMORY
c4 Int NULL AT=FIXED ST=DISK
-- Indexes --
PRIMARY KEY(c1) - UniqueHashIndex
i2(c3) - OrderedIndex
PRIMARY(c1) - OrderedIndex
i1(c2) - OrderedIndex
NDBT_ProgramExit: 0 - OK
性能注意事项。 使用 Disk Data 存储的集群的性能将大大改善,如果 Disk Data 文件被保存在与数据节点文件系统不同的物理磁盘上。对于集群中的每个数据节点,这都是必需的,以获得明显的性能改善。
您可以使用绝对路径和相对文件系统路径与 ADD UNDOFILE
和 ADD DATAFILE
;相对路径是相对于数据节点的数据目录计算的。
日志文件组、表空间和使用这些 Disk Data 表必须按特定顺序创建。这也是删除这些对象时的限制,受以下约束:
-
只要任何表空间使用日志文件组,就不能删除日志文件组。
-
只要表空间包含任何数据文件,就不能删除表空间。
-
只要仍有表使用表空间,就不能从表空间中删除任何数据文件。
-
不能删除与其他表空间关联的文件,而不是与其创建的表空间。
例如,要删除本节中创建的所有对象,可以使用以下语句:
mysql> DROP TABLE dt_1;
mysql> ALTER TABLESPACE ts_1
-> DROP DATAFILE 'data_2.dat'
-> ENGINE NDBCLUSTER;
mysql> ALTER TABLESPACE ts_1
-> DROP DATAFILE 'data_1.dat'
-> ENGINE NDBCLUSTER;
mysql> DROP TABLESPACE ts_1
-> ENGINE NDBCLUSTER;
mysql> DROP LOGFILE GROUP lg_1
-> ENGINE NDBCLUSTER;
这些语句必须按照显示的顺序执行,除了两个 ALTER TABLESPACE ... DROP DATAFILE
语句可以以任意顺序执行。