21.2.7 具有 table 和数据的 NDB 群集示例
Note
本节中的信息适用于在 Unix 和 Windows 平台上运行的 NDB Cluster。
在 NDB Cluster 中使用数据库 table 和数据与在标准 MySQL 中进行操作没有太大区别。需要牢记两个关键点:
- 对于要在群集中复制的 table,它必须使用NDBCLUSTER存储引擎。要指定此选项,请在创建 table 时使用
ENGINE=NDBCLUSTER
或ENGINE=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
示例数据库,并且要导出City
table:
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 数据库之前,对其进行修改。以City
table 为例,修改定义的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_name
或ENGINE=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 mysqli
extensions 执行刚刚显示的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 一样。