21.2.7 具有 table 和数据的 NDB 群集示例

Note

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

在 NDB Cluster 中使用数据库 table 和数据与在标准 MySQL 中进行操作没有太大区别。需要牢记两个关键点:

  • 对于要在群集中复制的 table,它必须使用NDBCLUSTER存储引擎。要指定此选项,请在创建 table 时使用ENGINE=NDBCLUSTERENGINE=NDB选项:
CREATE TABLE tbl_name (col_name column_definitions) ENGINE=NDBCLUSTER;

或者,对于使用不同存储引擎的现有 table,使用ALTER TABLE将 table 更改为使用NDBCLUSTER

ALTER TABLE tbl_name ENGINE=NDBCLUSTER;
  • 每个NDBCLUSTERtable 都有一个主键。如果在创建 table 时用户未定义主键,则NDBCLUSTER存储引擎会自动生成一个隐藏的主键。这样的键就像其他任何 table 索引一样占用空间。 (由于存储空间不足,无法容纳这些自动创建的索引,遇到问题并不罕见.)

如果要使用mysqldump的输出从现有数据库中导入 table,则可以在文本编辑器中打开 SQL 脚本,并将ENGINE选项添加到任何 table 创建语句中,或替换任何现有的ENGINE选项。假设您在另一台不支持 NDB 群集的 MySQL 服务器上具有world示例数据库,并且要导出Citytable:

shell> mysqldump --add-drop-table world City > city_table.sql

结果city_table.sql文件将包含此 table 创建语句(以及导入 table 数据所必需的INSERT语句):

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 使用此 table 的NDBCLUSTER存储引擎。有两种方法可以完成此操作。其中之一是在将 table 定义导入到 Cluster 数据库之前,对其进行修改。以Citytable 为例,修改定义的ENGINE选项,如下所示:

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)

必须对要成为集群数据库一部分的每个 table 进行定义。实现此目的的最简单方法是在包含定义的文件上进行搜索和替换,并将TYPE=engine_nameENGINE=engine_name的所有实例替换为ENGINE=NDBCLUSTER。如果您不想修改文件,则可以使用未修改的文件来创建 table,然后使用ALTER TABLE来更改其存储引擎。详细信息将在本节后面给出。

假设您已经在集群的 SQL 节点上创建了名为world的数据库,则可以使用mysql命令行 Client 端读取city_table.sql,并以通常的方式创建并填充相应的 table:

shell> mysql world < city_table.sql

请记住,必须在运行 SQL 节点的主机上(在这种情况下,在 IP 地址为198.51.100.20的计算机上)执行前面的命令,这一点非常重要。

要在 SQL 节点上创建整个world数据库的副本,请在非群集服务器上使用mysqldump将数据库导出到名为world.sql的文件中(例如,在/tmp目录中)。然后按照上述说明修改 table 定义,并将文件导入群集的 SQL 节点,如下所示:

shell> mysql world < /tmp/world.sql

如果将文件保存到其他位置,请相应地调整上述说明。

在 SQL 节点上运行SELECT查询与在 MySQL 服务器的任何其他实例上运行它们无异。要从命令行运行查询,您首先需要以通常的方式登录 MySQL Monitor(在Enter password:提示符下指定root密码):

shell> 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: 5.7.31-ndb-7.5.20

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

mysql>

我们仅使用 MySQL 服务器的root帐户,并假定您已遵循安装 MySQL 服务器的标准安全预防措施,包括设置了一个强root密码。有关更多信息,请参见第 2.10.4 节“保护初始 MySQL 帐户”

值得考虑的是,群集节点在彼此访问时不会使用 MySQL 特权系统。设置或更改 MySQL 用户帐户(包括root帐户)仅影响访问 SQL 节点的应用程序,而不影响节点之间的交互。有关更多信息,请参见第 21.5.17.2 节“ NDB 群集和 MySQL 特权”

如果在导入 SQL 脚本之前未在 table 定义中修改ENGINE子句,则此时应运行以下语句:

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

选择数据库并对该数据库中的 table 运行 SELECT 查询也可以通过通常的方式来完成,就像退出 MySQL Monitor 一样:

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

shell>

使用 MySQL 的应用程序可以使用标准 API 来访问NDBtable。重要的是要记住,您的应用程序必须访问 SQL 节点,而不是 Management 或数据节点。这个简短的示例说明了如何使用运行在网络上其他位置的 Web 服务器上的 PHP 5.X mysqliextensions 执行刚刚显示的SELECT语句:

<!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 一样。