#### 23.6.7.3 在线添加 NDB Cluster 数据节点：详细示例

在本节中，我们提供了一个详细示例，说明如何在线添加新的 NDB Cluster 数据节点，从单个节点组中具有 2 个数据节点的 NDB Cluster 开始，到在 2 个节点组中具有 4 个数据节点的集群结束。

**开始配置。**出于说明的目的，我们假设一个最小配置，并且集群使用`配置文件`文件仅包含以下信息：

```
[ndbd default]
DataMemory = 100M
IndexMemory = 100M
NoOfReplicas = 2
DataDir = /usr/local/mysql/var/mysql-cluster

[ndbd]
Id = 1
HostName = 198.51.100.1

[ndbd]
Id = 2
HostName = 198.51.100.2

[mgm]
HostName = 198.51.100.10
Id = 10

[api]
Id=20
HostName = 198.51.100.20

[api]
Id=21
HostName = 198.51.100.21
```

笔记

我们在数据节点 ID 和其他节点之间的序列中留下了空隙。这使得以后更容易将尚未使用的节点 ID 分配给新添加的数据节点。

我们还假设您已经使用适当的命令行启动了集群，或者`我的.cnf`选项，并且运行[`显示`](mysql-cluster-mgm-client-commands.html#ndbclient-show)在管理客户端中产生类似于此处显示的输出：

```
-- NDB Cluster -- Management Client --
ndb_mgm> SHOW
Connected to Management Server at: 198.51.100.10:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=1    @198.51.100.1  (8.0.29-ndb-8.0.29, Nodegroup: 0, *)
id=2    @198.51.100.2  (8.0.29-ndb-8.0.29, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=10   @198.51.100.10  (8.0.29-ndb-8.0.29)

[mysqld(API)]   2 node(s)
id=20   @198.51.100.20  (8.0.29-ndb-8.0.29)
id=21   @198.51.100.21  (8.0.29-ndb-8.0.29)
```

最后，我们假设集群包含一个[`NDBCLUSTER`](mysql-cluster.html)创建的表如下所示：

```
USE n;

CREATE TABLE ips (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    country_code CHAR(2) NOT NULL,
    type CHAR(4) NOT NULL,
    ip_address VARCHAR(15) NOT NULL,
    addresses BIGINT UNSIGNED DEFAULT NULL,
    date BIGINT UNSIGNED DEFAULT NULL
)   ENGINE NDBCLUSTER;
```

本节后面显示的内存使用情况和相关信息是在向该表中插入大约 50000 行后生成的。

笔记

在这个例子中，我们展示了单线程[**ndbd**](mysql-cluster-programs-ndbd.html)用于数据节点进程。如果您使用的是多线程，您也可以应用此示例[**ndbmtd**](mysql-cluster-programs-ndbmtd.html)通过替换[**ndbmtd**](mysql-cluster-programs-ndbmtd.html)为了[**ndbd**](mysql-cluster-programs-ndbd.html)出现在以下步骤中的任何位置。

**第一步：更新配置文件。**在文本编辑器中打开集群全局配置文件并添加`[ndbd]`对应于 2 个新数据节点的部分。（我们给这些数据节点 ID 3 和 4，并假设它们分别在地址 198.51.100.3 和 198.51.100.4 的主机上运行。）添加新部分后，`配置文件`文件应类似于此处显示的内容，其中添加的文件以粗体显示：

```
[ndbd default]
DataMemory = 100M
IndexMemory = 100M
NoOfReplicas = 2
DataDir = /usr/local/mysql/var/mysql-cluster

[ndbd]
Id = 1
HostName = 198.51.100.1

[ndbd]
Id = 2
HostName = 198.51.100.2

[ndbd]
Id = 3
HostName = 198.51.100.3

[ndbd]
Id = 4
HostName = 198.51.100.4

[mgm]
HostName = 198.51.100.10
Id = 10

[api]
Id=20
HostName = 198.51.100.20

[api]
Id=21
HostName = 198.51.100.21
```

进行必要的更改后，保存文件。

**步骤 2：重新启动管理服务器。**重新启动集群管理服务器需要您发出单独的命令来停止管理服务器，然后重新启动它，如下所示：

1.  使用管理客户端停止管理服务器[`停止`](mysql-cluster-mgm-client-commands.html#ndbclient-stop)命令，如下所示：

    ```
    ndb_mgm> 10 STOP
    Node 10 has shut down.
    Disconnecting to allow Management Server to shutdown

    $>
    ```

2.  因为关闭管理服务器会导致管理客户端终止，所以您必须从系统 shell 启动管理服务器。为简单起见，我们假设`配置文件`与管理服务器二进制文件位于同一目录中，但实际上，您必须提供配置文件的正确路径。您还必须提供[`--重新加载`](mysql-cluster-programs-ndb-mgmd.html#option_ndb_mgmd_reload)要么[`- 最初的`](mysql-cluster-programs-ndb-mgmd.html#option_ndb_mgmd_initial)选项，以便管理服务器从文件而不是其配置缓存中读取新配置。如果您的 shell 的当前目录也与管理服务器二进制文件所在的目录相同，那么您可以调用管理服务器，如下所示：

    ```
    $> ndb_mgmd -f config.ini --reload
    2008-12-08 17:29:23 [MgmSrvr] INFO     -- NDB Cluster Management Server. 8.0.29-ndb-8.0.29
    2008-12-08 17:29:23 [MgmSrvr] INFO     -- Reading cluster configuration from 'config.ini'
    ```

    如果你检查输出[`显示`](mysql-cluster-mgm-client-commands.html#ndbclient-show)重新启动后在管理客户端中[**数据库\_毫克**](mysql-cluster-programs-ndb-mgm.html)过程中，您现在应该看到如下内容：


```
-- NDB Cluster -- Management Client --
ndb_mgm> SHOW
Connected to Management Server at: 198.51.100.10:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=1    @198.51.100.1  (8.0.29-ndb-8.0.29, Nodegroup: 0, *)
id=2    @198.51.100.2  (8.0.29-ndb-8.0.29, Nodegroup: 0)
id=3 (not connected, accepting connect from 198.51.100.3)
id=4 (not connected, accepting connect from 198.51.100.4)

[ndb_mgmd(MGM)] 1 node(s)
id=10   @198.51.100.10  (8.0.29-ndb-8.0.29)

[mysqld(API)]   2 node(s)
id=20   @198.51.100.20  (8.0.29-ndb-8.0.29)
id=21   @198.51.100.21  (8.0.29-ndb-8.0.29)
```

**步骤 3：对现有数据节点执行滚动重启。**此步骤可以完全在集群管理客户端中使用[`重新开始`](mysql-cluster-mgm-client-commands.html#ndbclient-restart)命令，如下所示：

```
ndb_mgm> 1 RESTART
Node 1: Node shutdown initiated
Node 1: Node shutdown completed, restarting, no start.
Node 1 is being restarted

ndb_mgm> Node 1: Start initiated (version 8.0.29)
Node 1: Started (version 8.0.29)

ndb_mgm> 2 RESTART
Node 2: Node shutdown initiated
Node 2: Node shutdown completed, restarting, no start.
Node 2 is being restarted

ndb_mgm> Node 2: Start initiated (version 8.0.29)

ndb_mgm> Node 2: Started (version 8.0.29)
```

重要的

每次发出后`*`X`* 重新开始`命令，等到管理客户端报告`节点 *`X`*：开始（版本...）` *前*继续进行。

您可以通过检查[`ndbinfo.no​​des`](mysql-cluster-ndbinfo-nodes.html)表中的[**mysql**](mysql.html)客户。

**步骤 4：对所有集群 API 节点执行滚动重启。**使用以下命令关闭并重新启动充当集群中 SQL 节点的每个 MySQL 服务器[**mysqladmin 关闭**](mysqladmin.html)其次是[**mysqld\_安全的**](mysqld-safe.html)（或另一个启动脚本）。这应该类似于此处显示的内容，其中*`密码`*是 MySQL`根`给定 MySQL 服务器实例的密码：

```
$> mysqladmin -uroot -ppassword shutdown
081208 20:19:56 mysqld_safe mysqld from pid file
/usr/local/mysql/var/tonfisk.pid ended
$> mysqld_safe --ndbcluster --ndb-connectstring=198.51.100.10 &
081208 20:20:06 mysqld_safe Logging to '/usr/local/mysql/var/tonfisk.err'.
081208 20:20:06 mysqld_safe Starting mysqld daemon with databases
from /usr/local/mysql/var
```

当然，确切的输入和输出取决于 MySQL 在系统上的安装方式和位置，以及您选择启动它的选项（以及这些选项中的部分或全部是否在`我的.cnf`文件）。

**步骤 5：执行新数据节点的初始启动。**从新数据节点的每个主机上的系统 shell，启动数据节点，如下所示，使用[`- 最初的`](mysql-cluster-programs-ndbd.html#option_ndbd_initial)选项：

```
$> ndbd -c 198.51.100.10 --initial
```

笔记

不同于重启已有数据节点的情况，可以同时启动新的数据节点；您无需等待一个完成启动后再启动另一个。

*等到两个新数据节点都启动后，再继续下一步*.新数据节点启动后，您可以在管理客户端的输出中看到[`显示`](mysql-cluster-mgm-client-commands.html#ndbclient-show)命令它们还不属于任何节点组（如这里用粗体表示的那样）：

```
ndb_mgm> SHOW
Connected to Management Server at: 198.51.100.10:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=1    @198.51.100.1  (8.0.29-ndb-8.0.29, Nodegroup: 0, *)
id=2    @198.51.100.2  (8.0.29-ndb-8.0.29, Nodegroup: 0)
id=3    @198.51.100.3  (8.0.29-ndb-8.0.29, no nodegroup)
id=4    @198.51.100.4  (8.0.29-ndb-8.0.29, no nodegroup)

[ndb_mgmd(MGM)] 1 node(s)
id=10   @198.51.100.10  (8.0.29-ndb-8.0.29)

[mysqld(API)]   2 node(s)
id=20   @198.51.100.20  (8.0.29-ndb-8.0.29)
id=21   @198.51.100.21  (8.0.29-ndb-8.0.29)
```

**第 6 步：创建一个新的节点组。**您可以通过发出[`创建节点组`](mysql-cluster-mgm-client-commands.html#ndbclient-create-nodegroup)集群管理客户端中的命令。此命令将要包含在新节点组中的数据节点的节点 ID 的逗号分隔列表作为其参数，如下所示：

```
ndb_mgm> CREATE NODEGROUP 3,4
Nodegroup 1 created
```

通过发行[`显示`](mysql-cluster-mgm-client-commands.html#ndbclient-show)再次，您可以验证数据节点 3 和 4 是否已加入新节点组（再次以粗体表示）：

```
ndb_mgm> SHOW
Connected to Management Server at: 198.51.100.10:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=1    @198.51.100.1  (8.0.29-ndb-8.0.29, Nodegroup: 0, *)
id=2    @198.51.100.2  (8.0.29-ndb-8.0.29, Nodegroup: 0)
id=3    @198.51.100.3  (8.0.29-ndb-8.0.29, Nodegroup: 1)
id=4    @198.51.100.4  (8.0.29-ndb-8.0.29, Nodegroup: 1)

[ndb_mgmd(MGM)] 1 node(s)
id=10   @198.51.100.10  (8.0.29-ndb-8.0.29)

[mysqld(API)]   2 node(s)
id=20   @198.51.100.20  (8.0.29-ndb-8.0.29)
id=21   @198.51.100.21  (8.0.29-ndb-8.0.29)
```

**第 7 步：重新分配集群数据。**创建节点组时，现有数据和索引不会自动分发到新节点组的数据节点，您可以通过发出适当的[`报告`](mysql-cluster-mgm-client-commands.html#ndbclient-report)管理客户端中的命令：

```
ndb_mgm> ALL REPORT MEMORY

Node 1: Data usage is 5%(177 32K pages of total 3200)
Node 1: Index usage is 0%(108 8K pages of total 12832)
Node 2: Data usage is 5%(177 32K pages of total 3200)
Node 2: Index usage is 0%(108 8K pages of total 12832)
Node 3: Data usage is 0%(0 32K pages of total 3200)
Node 3: Index usage is 0%(0 8K pages of total 12832)
Node 4: Data usage is 0%(0 32K pages of total 3200)
Node 4: Index usage is 0%(0 8K pages of total 12832)
```

通过使用[**数据库\_描述**](mysql-cluster-programs-ndb-desc.html)与`-p`选项，这会导致输出包含分区信息，您可以看到该表仍然只使用 2 个分区（在`每个分区信息`输出部分，此处以粗体显示）：

```
$> ndb_desc -c 198.51.100.10 -d n ips -p
-- ips --
Version: 1
Fragment type: 9
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 6
Number of primary keys: 1
Length of frm data: 340
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
FragmentCount: 2
TableStatus: Retrieved
-- Attributes --
id Bigint PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
country_code Char(2;latin1_swedish_ci) NOT NULL AT=FIXED ST=MEMORY
type Char(4;latin1_swedish_ci) NOT NULL AT=FIXED ST=MEMORY
ip_address Varchar(15;latin1_swedish_ci) NOT NULL AT=SHORT_VAR ST=MEMORY
addresses Bigunsigned NULL AT=FIXED ST=MEMORY
date Bigunsigned NULL AT=FIXED ST=MEMORY

-- Indexes --
PRIMARY KEY(id) - UniqueHashIndex
PRIMARY(id) - OrderedIndex

-- Per partition info --
Partition   Row count   Commit count  Frag fixed memory   Frag varsized memory
0           26086       26086         1572864             557056
1           26329       26329         1605632             557056

NDBT_ProgramExit: 0 - OK
```

您可以通过对每个数据节点执行[`新开发银行`](mysql-cluster.html)表，一个[`ALTER TABLE ...算法=INPLACE，重新组织分区`](alter-table.html)中的声明[**mysql**](mysql.html)客户。

重要的

`ALTER TABLE ...算法=INPLACE，重新组织分区`不适用于使用`MAX_ROWS`选项。相反，使用`更改表...算法=INPLACE，MAX_ROWS=...`重组这些表格。

请记住，使用`MAX_ROWS`不推荐设置每个表的分区数，您应该使用`PARTITION_BALANCE`反而;看[第 13.1.20.11 节，“设置 NDB 评论选项”](create-table-ndb-comment-options.html)， 了解更多信息。

发表声明后`ALTER TABLE ips ALGORITHM=INPLACE，重新组织分区`，你可以看到使用[**数据库\_描述**](mysql-cluster-programs-ndb-desc.html)该表的数据现在使用 4 个分区存储，如下所示（输出的相关部分以粗体显示）：

```
$> ndb_desc -c 198.51.100.10 -d n ips -p
-- ips --
Version: 16777217
Fragment type: 9
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 6
Number of primary keys: 1
Length of frm data: 341
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
FragmentCount: 4
TableStatus: Retrieved
-- Attributes --
id Bigint PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
country_code Char(2;latin1_swedish_ci) NOT NULL AT=FIXED ST=MEMORY
type Char(4;latin1_swedish_ci) NOT NULL AT=FIXED ST=MEMORY
ip_address Varchar(15;latin1_swedish_ci) NOT NULL AT=SHORT_VAR ST=MEMORY
addresses Bigunsigned NULL AT=FIXED ST=MEMORY
date Bigunsigned NULL AT=FIXED ST=MEMORY

-- Indexes --
PRIMARY KEY(id) - UniqueHashIndex
PRIMARY(id) - OrderedIndex

-- Per partition info --
Partition   Row count   Commit count  Frag fixed memory   Frag varsized memory
0           12981       52296         1572864             557056
1           13236       52515         1605632             557056
2           13105       13105         819200              294912
3           13093       13093         819200              294912

NDBT_ProgramExit: 0 - OK
```

笔记

一般，[`更改表 *`表名`* [ALGORITHM=INPLACE,] 重新组织分区`](alter-table.html)与分区标识符列表和一组分区定义一起使用，为已显式分区的表创建新的分区方案。它在这里用于将数据重新分配到新的 NDB Cluster 节点组在这方面是一个例外；以这种方式使用时，没有其他关键字或标识符跟随`重组分区`.

有关详细信息，请参阅[第 13.1.9 节，“ALTER TABLE 语句”](alter-table.html).

此外，对于每个表，[`更改表`](alter-table.html)声明后应跟一个[`优化表`](optimize-table.html)回收浪费的空间。您可以获得所有列表[`NDBCLUSTER`](mysql-cluster.html)使用以下查询的表[`INFORMATION_SCHEMA.TABLES`](information-schema-tables-table.html)桌子：

```
SELECT TABLE_SCHEMA, TABLE_NAME
    FROM INFORMATION_SCHEMA.TABLES
    WHERE ENGINE = 'NDBCLUSTER';
```

笔记

这`INFORMATION_SCHEMA.TABLES.ENGINE`NDB Cluster 表的值始终为[`NDBCLUSTER`](mysql-cluster.html)，无论是否`创建表`用于创建表的语句（或[`更改表`](alter-table.html)用于从不同存储引擎转换现有表的语句）使用[`新开发银行`](mysql-cluster.html)要么[`NDBCLUSTER`](mysql-cluster.html)在其`引擎`选项。

您可以在执行这些语句后在输出中看到[`所有报告内存`](mysql-cluster-mgm-client-commands.html#ndbclient-report)数据和索引现在在所有集群数据节点之间重新分配，如下所示：

```
ndb_mgm> ALL REPORT MEMORY

Node 1: Data usage is 5%(176 32K pages of total 3200)
Node 1: Index usage is 0%(76 8K pages of total 12832)
Node 2: Data usage is 5%(176 32K pages of total 3200)
Node 2: Index usage is 0%(76 8K pages of total 12832)
Node 3: Data usage is 2%(80 32K pages of total 3200)
Node 3: Index usage is 0%(51 8K pages of total 12832)
Node 4: Data usage is 2%(80 32K pages of total 3200)
Node 4: Index usage is 0%(50 8K pages of total 12832)
```

笔记

由于只有一个 DDL 操作[`NDBCLUSTER`](mysql-cluster.html)表可以一次执行，您必须等待每个[`ALTER TABLE ...重新组织分区`](alter-table.html)声明在发出下一个之前完成。

没有必要发出[`ALTER TABLE ...重新组织分区`](alter-table.html)声明为[`NDBCLUSTER`](mysql-cluster.html)创建的表*后*添加了新的数据节点；添加到此类表中的数据会自动分布在所有数据节点中。然而，在[`NDBCLUSTER`](mysql-cluster.html)存在的表*之前*添加新节点后，现有数据和新数据都不会使用新节点分发，直到这些表已使用重新组织[`ALTER TABLE ...重新组织分区`](alter-table.html).

**替代程序，无需滚动重启。**首次启动集群时，可以通过配置额外的数据节点而不是启动它们来避免滚动重启的需要。和以前一样，我们假设您希望从一个节点组中的两个数据节点（节点 1 和 2）开始，然后通过添加由节点 3 和 4 组成的第二个节点组，将集群扩展到四个数据节点：

```
[ndbd default]
DataMemory = 100M
IndexMemory = 100M
NoOfReplicas = 2
DataDir = /usr/local/mysql/var/mysql-cluster

[ndbd]
Id = 1
HostName = 198.51.100.1

[ndbd]
Id = 2
HostName = 198.51.100.2

[ndbd]
Id = 3
HostName = 198.51.100.3
Nodegroup = 65536

[ndbd]
Id = 4
HostName = 198.51.100.4
Nodegroup = 65536

[mgm]
HostName = 198.51.100.10
Id = 10

[api]
Id=20
HostName = 198.51.100.20

[api]
Id=21
HostName = 198.51.100.21
```

稍后要联机的数据节点（节点 3 和 4）可以配置为[`节点组 = 65536`](mysql-cluster-ndbd-definition.html#ndbparam-ndbd-nodegroup)，在这种情况下，节点 1 和 2 可以分别启动，如下所示：

```
$> ndbd -c 198.51.100.10 --initial
```

配置的数据节点[`节点组 = 65536`](mysql-cluster-ndbd-definition.html#ndbparam-ndbd-nodegroup)管理服务器将其视为您已使用启动节点 1 和 2[`--nowait-nodes=3,4`](mysql-cluster-programs-ndbd.html#option_ndbd_nowait-nodes)等待一段时间后，由设置确定[`StartNoNodeGroupTimeout`](mysql-cluster-ndbd-definition.html#ndbparam-ndbd-startnonodegrouptimeout)数据节点配置参数。默认情况下，这是 15 秒（15000 毫秒）。

笔记

[`StartNoNodegroupTimeout`](mysql-cluster-ndbd-definition.html#ndbparam-ndbd-startnonodegrouptimeout)集群中所有数据节点必须相同；因此，您应该始终将其设置在`[ndbd 默认]`的部分`配置文件`文件，而不是单个数据节点。

当您准备好添加第二个节点组时，您只需执行以下附加步骤：

1.  启动数据节点 3 和 4，为每个新节点调用一次数据节点进程：

    ```
    $> ndbd -c 198.51.100.10 --initial
    ```

2.  发出适当的[`创建节点组`](mysql-cluster-mgm-client-commands.html#ndbclient-create-nodegroup)管理客户端中的命令：

    ```
    ndb_mgm> CREATE NODEGROUP 3,4
    ```

3.  在里面[**mysql**](mysql.html)客户，问题[`ALTER TABLE ...重新组织分区`](alter-table.html)和[`优化表`](optimize-table.html)每个现有的语句[`NDBCLUSTER`](mysql-cluster.html)桌子。（如本节其他地方所述，现有 NDB Cluster 表在完成之前无法使用新节点进行数据分发。）
