25.6.11.1 NDB 集群磁盘数据对象
NDB 集群磁盘数据存储使用以下对象实现:
-
表空间(Tablespace):作为其他磁盘数据对象的容器。一个表空间包含一个或多个数据文件和一个或多个undo日志文件组。
-
数据文件(Data file):存储列数据。数据文件直接分配给表空间。
-
Undo日志文件(Undo log file):包含回滚事务所需的undo信息。分配给undo日志文件组。
-
日志文件组(log file group):包含一个或多个undo日志文件。分配给表空间。
Undo日志文件和数据文件是每个数据节点的文件系统中的实际文件;默认情况下,它们将被放置在ndb_
中,指定在NDB 集群node_id
_fsconfig.ini
文件中的DataDir
路径中,其中node_id
是数据节点的节点ID。可以通过在创建undo日志或数据文件时指定绝对或相对路径来将它们放置到其他位置。后续在本节中显示这些语句。
Undo日志文件仅供磁盘数据表使用,不需要或不用于存储在内存中的NDB
表。
NDB 集群表空间和日志文件组不是文件实现的。
虽然不是所有磁盘数据对象都实现为文件,但是它们共享同一个命名空间。这意味着每个磁盘数据对象必须具有唯一的名称(而不仅是给定类型中的每个磁盘数据对象)。例如,你不能同时拥有一个表空间和日志文件组, ambos 命名为dd1
.
假设你已经设置了包含管理节点、SQL 节点的 NDB 集群,然后创建 NDB 集群表在磁盘上的基本步骤如下:
-
创建一个日志文件组,并将一个或多个回滚日志文件分配给它(回滚日志文件也称为undofile)。
-
创建一个表空间;将日志文件组,以及一个或多个数据文件,分配给表空间。
-
创建一个磁盘数据表,该表使用该表空间来存储数据。
这些任务可以使用在mysql客户端或其他 MySQL 客户端应用程序中执行 SQL 语句,例如以下示例所示。
-
我们使用
CREATE LOGFILE GROUP
创建一个名为lg_1
的日志文件组。这个日志文件组将由两个回滚日志文件组成,我们将其命名为undo_1.log
和undo_2.log
,初始大小分别为 16 MB 和 12 MB。 (默认的初始大小为 128 MB。) 可选地,您也可以指定日志文件组的回滚缓冲区的大小或让其采用默认值 8 MB。在这个示例中,我们将 UNDO 缓冲区的大小设置为 2 MB。一个日志文件组必须包含至少一个回滚日志文件,所以我们在这个CREATE LOGFILE GROUP
语句中添加undo_1.log
到lg_1
。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 集群中,至多只能存在一个日志文件组。
-
当您使用
DataDir
中的ndb_
目录在每个数据节点中创建一个 undo 日志文件时,文件名将是node_id
_fsfilename
。每个 undo 日志文件的大小由 SQL 语句指定。例如,如果 NDB 集群有 4 个数据节点,那么上面显示的ALTER LOGFILE GROUP
语句创建了 4 个 undo 日志文件,每个文件在每个数据节点的数据目录中,文件名为undo_2.log
,每个文件大小为 12 MB。 -
UNDO_BUFFER_SIZE
受系统内存可用量限制。 -
请查看第15.1.16节,“CREATE LOGFILE GROUP 语句”和第15.1.6节,“ALTER LOGFILE GROUP 语句”,了解这些语句的更多信息。
-
-
现在我们可以创建一个表空间—an abstract container for files used by Disk Data tables to store data。一个表空间与特定的日志文件组相关联;在创建新表空间时,您必须指定用于undo日志记录的日志文件组。您还需要至少指定一个数据文件;您可以在表空间创建后添加更多数据文件。也可以从表空间中删除数据文件(请参阅本节后面的示例)。
假设我们想创建一个名为
ts_1
的表空间,该表空间使用lg_1
作为其日志文件组。我们想要该表空间包含两个数据文件,名为data_1.dat
和data_2.dat
,初始大小分别为32 MB和48 MB(默认值为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
)。一些需要注意的项目:
-
与在本示例中用于undo日志文件的
.log
文件扩展名一样,.dat
文件扩展名没有特别的意义;它仅用于易于识别。 -
使用
ADD DATAFILE '
将数据文件添加到表空间时,会在每个数据节点的filename
'DataDir
目录中创建一个名为filename
的文件,wherenode_id
是数据节点的节点ID。每个数据文件的大小将根据SQL语句指定。例如,如果NDB集群有4个数据节点,那么上面显示的ALTER TABLESPACE
语句创建了4个数据文件,每个文件在对应的4个数据节点的数据目录中,各文件名为data_2.dat
,每个文件大小为48MB。 -
NDB
保留了每个表空间的4%用于数据节点重启时使用。这部分空间不可用来存储数据。 -
CREATE 表空间
语句必须包含一个ENGINE
子句;只能在使用相同存储引擎的表空间中创建表。对于NDB
表空间,ALTER 表空间
仅在ALTER 表空间 ... ADD DATAFILE
中接受一个ENGINE
子句,对于任何其他ALTER 表空间
语句,ENGINE
将被拒绝。对于NDB
表空间,ENGINE
选项的唯一允许值是NDBCLUSTER
和NDB
. -
对给定表空间中的所有数据文件执行extent分配操作,以轮询方式。
-
有关
CREATE 表空间
和ALTER 表空间
语句的更多信息,请见第15.1.21节,“CREATE 表空间语句”,和第15.1.10节,“ALTER 表空间语句”.
-
-
现在可以创建一个表,其中未索引的列存储在磁盘上,使用表空间
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
,您可以像对任何其他 MySQL 表一样执行INSERT
、SELECT
、UPDATE
和DELETE
语句。还可以使用
STORAGE
子句在CREATE TABLE
或ALTER TABLE
语句中定义列的定义中指定某个列是否存储在磁盘上或内存中。STORAGE DISK
将导致该列被存储在磁盘上,而STORAGE MEMORY
将导致使用内存存储。请参阅第15.1.20节,“CREATE TABLE 语句”,了解更多信息。
您可以通过查询 INFORMATION_SCHEMA
数据库中的 FILES
表来获取关于 NDB
硬盘数据文件和undo日志文件的信息,示例如下:
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节,“INFORMATION_SCHEMA FILES 表”。
磁盘上的列索引隐式存储. 对于前面示例中定义的表 dt_1
,只有 dob
和 joined
列被存储在磁盘上。这是因为对 id
、last_name
和 first_name
列的索引已经存在,因此这些列的数据存储在 RAM 中。只有未索引的列可以被存储在磁盘上;索引和索引列数据继续存储在内存中。这是 Disk Data 表设计时需要考虑的权衡:索引使用与 RAM 保持的平衡。
您不能将已明确声明为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
性能注意. 使用 Disk Data 存储的集群性能将大幅改善,如果 Disk Data 文件与数据节点文件系统分开存储。这必须对每个数据节点进行,以获得明显的性能提高。
您可以使用绝对和相对文件系统路径与ADD UNDOFILE
和 ADD DATAFILE
; 相对路径将根据数据节点的数据目录进行计算。
日志文件组、表空间和使用这些的 Disk Data 表必须按照特定的顺序创建。这同样适用于删除这些对象,subject to the following constraints:
-
不能在任何表空间使用它的情况下删除日志文件组。
-
不能在包含数据文件的情况下删除表空间。
-
不能在表空间中有任何表正在使用的情况下删除数据文件。
-
不能删除与其他表空间相关的文件,除非这些文件是与当前表空间相关的。
例如,要删除到目前为止在本节中创建的所有对象,可以使用以下语句:
mysql> DROP TABLE dt_1;
mysql> ALTER TABLESPACE ts_1
-> DROP DATAFILE 'data_2.dat';
mysql> ALTER TABLESPACE ts_1
-> DROP DATAFILE 'data_1.dat';
mysql> DROP TABLESPACE ts_1;
mysql> DROP LOGFILE GROUP lg_1;
这些语句必须按照显示的顺序执行,except that the two ALTER TABLESPACE ... DROP DATAFILE
statements may be executed in either order。
NDB 集群的 older 版本使用了ENGINE
子句与 ALTER TABLESPACE ... DROP DATAFILE
和 DROP TABLESPACE
。从 NDB 8.4 开始,这些语句在这两个语句中不再支持。