### 23.3.5 带有表和数据的 NDB 集群示例

[](<>)[](<>)

笔记

本节中的信息适用于在 Unix 和 Windows 平台上运行的 NDB Cluster。

在 NDB Cluster 中处理数据库表和数据与在标准 MySQL 中处理没有太大区别。有两个关键点要记住：

-   对于要在集群中复制的表，它必须使用[`NDBCLUSTER`](mysql-cluster.html)存储引擎。要指定这一点，请使用`引擎=NDBCLUSTER`要么`引擎=NDB`创建表时的选项：

    ```
    CREATE TABLE tbl_name (col_name column_definitions) ENGINE=NDBCLUSTER;
    ```

    或者，对于使用不同存储引擎的现有表，请使用[`更改表`](alter-table.html)更改要使用的表[`NDBCLUSTER`](mysql-cluster.html)：

    ```
    ALTER TABLE tbl_name ENGINE=NDBCLUSTER;
    ```

-   每一个[`NDBCLUSTER`](mysql-cluster.html)表有一个主键。如果创建表时用户没有定义主键，则[`NDBCLUSTER`](mysql-cluster.html)存储引擎自动生成一个隐藏的。这样的键占用空间，就像任何其他表索引一样。（由于存储这些自动创建的索引的内存不足而遇到问题并不少见。）

    如果您使用以下输出从现有数据库中导入表[**mysql转储**](mysqldump.html)，您可以在文本编辑器中打开 SQL 脚本并添加`引擎`任何表创建语句的选项，或替换任何现有的`引擎`选项。假设你有`世界`另一个不支持 NDB Cluster 的 MySQL 服务器上的示例数据库，并且您想要导出`城市`桌子：


```
$> mysqldump --add-drop-table world City > city_table.sql
```

所结果的`city_table.sql`文件包含此表创建语句（和[`插入`](insert.html)导入表数据所需的语句）：

```
DROP TABLE IF EXISTS `City`;
CREATE TABLE `City` (
  `ID` int(11) NOT NULL auto_increment,
  `Name` char(35) NOT NULL default '',
  `CountryCode` char(3) NOT NULL default '',
  `District` char(20) NOT NULL default '',
  `Population` int(11) NOT NULL default '0',
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO `City` VALUES (1,'Kabul','AFG','Kabol',1780000);
INSERT INTO `City` VALUES (2,'Qandahar','AFG','Qandahar',237500);
INSERT INTO `City` VALUES (3,'Herat','AFG','Herat',186800);
(remaining INSERT statements omitted)
```

您需要确保 MySQL 使用[`NDBCLUSTER`](mysql-cluster.html)此表的存储引擎。有两种方法可以实现这一点。其中之一是修改表定义*前*将其导入集群数据库。使用`城市`以表为例，修改`引擎`定义选项如下：

```
DROP TABLE IF EXISTS `City`;
CREATE TABLE `City` (
  `ID` int(11) NOT NULL auto_increment,
  `Name` char(35) NOT NULL default '',
  `CountryCode` char(3) NOT NULL default '',
  `District` char(20) NOT NULL default '',
  `Population` int(11) NOT NULL default '0',
  PRIMARY KEY  (`ID`)
) ENGINE=NDBCLUSTER DEFAULT CHARSET=latin1;

INSERT INTO `City` VALUES (1,'Kabul','AFG','Kabol',1780000);
INSERT INTO `City` VALUES (2,'Qandahar','AFG','Qandahar',237500);
INSERT INTO `City` VALUES (3,'Herat','AFG','Herat',186800);
(remaining INSERT statements omitted)
```

这必须为要成为集群数据库一部分的每个表的定义完成。完成此操作的最简单方法是对包含定义的文件进行搜索和替换，并替换`类型=*`引擎名称`*`要么`引擎=*`引擎名称`*`和`引擎=NDBCLUSTER`.如果不想修改文件，可以使用未修改的文件创建表，然后使用[`更改表`](alter-table.html)改变他们的存储引擎。细节在本节后面给出。

假设您已经创建了一个名为`世界`在集群的 SQL 节点上，您可以使用[**mysql**](mysql.html)要读取的命令行客户端`city_table.sql`，并以通常的方式创建和填充相应的表：

```
$> mysql world < city_table.sql
```

非常重要的一点要记住，前面的命令必须在运行 SQL 节点的主机上执行（在这种情况下，在具有 IP 地址的机器上）`198.51.100.20`）。

创建整个副本`世界`SQL 节点上的数据库，使用[**mysql转储**](mysqldump.html)在非集群服务器上将数据库导出到名为`世界.sql`（例如，在`/tmp`目录）。然后按照刚才的描述修改表定义，并将文件导入集群的 SQL 节点，如下所示：

```
$> mysql world < /tmp/world.sql
```

如果您将文件保存到其他位置，请相应地调整前面的说明。

跑步[`选择`](select.html)SQL 节点上的查询与在 MySQL 服务器的任何其他实例上运行它们没有什么不同。要从命令行运行查询，首先需要以通常的方式登录到 MySQL Monitor（指定`根`密码在`输入密码：`迅速的）：

```
$> mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 8.0.29-ndb-8.0.29

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>
```

我们只是使用 MySQL 服务器的`根`帐户并假设您已遵循安装 MySQL 服务器的标准安全预防措施，包括设置强`根`密码。有关详细信息，请参阅[第 2.10.4 节，“保护初始 MySQL 帐户”](default-privileges.html).

值得考虑的是 NDB Cluster 节点确实*不是*相互访问时使用 MySQL 特权系统。设置或更改 MySQL 用户帐户（包括`根`account) 只影响访问 SQL 节点的应用程序，而不影响节点之间的交互。看[第 23.6.18.2 节，“NDB 集群和 MySQL 特权”](mysql-cluster-security-mysql-privileges.html)， 了解更多信息。

如果你没有修改`引擎`在导入 SQL 脚本之前表定义中的子句，此时您应该运行以下语句：

```
mysql> USE world;
mysql> ALTER TABLE City ENGINE=NDBCLUSTER;
mysql> ALTER TABLE Country ENGINE=NDBCLUSTER;
mysql> ALTER TABLE CountryLanguage ENGINE=NDBCLUSTER;
```

选择数据库并运行**选择**对该数据库中的表的查询也以通常的方式完成，就像退出 MySQL 监视器一样：

```
mysql> USE world;
mysql> SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5;
+-----------+------------+
| Name      | Population |
+-----------+------------+
| Bombay    |   10500000 |
| Seoul     |    9981619 |
| São Paulo |    9968485 |
| Shanghai  |    9696300 |
| Jakarta   |    9604900 |
+-----------+------------+
5 rows in set (0.34 sec)

mysql> \q
Bye

$>
```

使用 MySQL 的应用程序可以使用标准 API 来访问[`新开发银行`](mysql-cluster.html)表。请务必记住，您的应用程序必须访问 SQL 节点，而不是管理或数据节点。这个简短的例子展示了我们如何执行[`选择`](select.html)刚刚使用 PHP 5.X 显示的语句`mysqli`在网络上其他地方的 Web 服务器上运行的扩展：

```
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type"
           content="text/html; charset=iso-8859-1">
  <title>SIMPLE mysqli SELECT</title>
</head>
<body>
<?php
  # connect to SQL node:
  $link = new mysqli('198.51.100.20', 'root', 'root_password', 'world');
  # parameters for mysqli constructor are:
  #   host, user, password, database

  if( mysqli_connect_errno() )
    die("Connect failed: " . mysqli_connect_error());

  $query = "SELECT Name, Population
            FROM City
            ORDER BY Population DESC
            LIMIT 5";

  # if no errors...
  if( $result = $link->query($query) )
  {
?>
<table border="1" width="40%" cellpadding="4" cellspacing ="1">
  <tbody>
  <tr>
    <th width="10%">City</th>
    <th>Population</th>
  </tr>
<?
    # then display the results...
    while($row = $result->fetch_object())
      printf("<tr>\n  <td align=\"center\">%s</td><td>%d</td>\n</tr>\n",
              $row->Name, $row->Population);
?>
  </tbody
</table>
<?
  # ...and verify the number of rows that were retrieved
    printf("<p>Affected rows: %d</p>\n", $link->affected_rows);
  }
  else
    # otherwise, tell us what went wrong
    echo mysqli_error();

  # free the result set and the mysqli connection object
  $result->close();
  $link->close();
?>
</body>
</html>
```

我们假设运行在 Web 服务器上的进程可以到达 SQL 节点的 IP 地址。

以类似的方式，您可以使用 MySQL C API、Perl-DBI、Python-mysql 或 MySQL 连接器来执行数据定义和操作任务，就像您通常使用 MySQL 一样。
