本节中的信息适用于在 Unix 和 Windows 平台上运行的 NDB 集群。
在 NDB 集群中使用数据库表和数据与在标准 MySQL 中的操作没有太大区别。需要牢记两个关键点
要使表在集群中复制,它必须使用
NDBCLUSTER
存储引擎。要指定它,请在创建表时使用ENGINE=NDBCLUSTER
或ENGINE=NDB
选项CREATE TABLE tbl_name (col_name column_definitions) ENGINE=NDBCLUSTER;
或者,对于使用不同存储引擎的现有表,请使用
ALTER TABLE
将表更改为使用NDBCLUSTER
ALTER TABLE tbl_name ENGINE=NDBCLUSTER;
每个
NDBCLUSTER
表都有一个主键。如果在创建表时用户没有定义主键,则NDBCLUSTER
存储引擎会自动生成一个隐藏的主键。这样的键与任何其他表索引一样占用空间。(由于没有足够的内存来容纳这些自动创建的索引而遇到问题并不少见。)
如果您使用 mysqldump 的输出来从现有数据库导入表,则可以在文本编辑器中打开 SQL 脚本,并将 ENGINE
选项添加到任何表创建语句中,或替换任何现有的 ENGINE
选项。假设您在不支持 NDB 集群的另一个 MySQL 服务器上有 world
示例数据库,并且您想导出 City
表
$> mysqldump --add-drop-table world City > city_table.sql
生成的 city_table.sql
文件包含此表创建语句(以及导入表数据所需的 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;
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
存储引擎。可以通过两种方式实现这一点。其中一种方法是在将表定义导入到集群数据库 之前 修改它。以 City
表为例,修改定义的 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;
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)
对于要成为集群数据库一部分的每个表的定义,都必须执行此操作。完成此操作的最简单方法是对包含定义的文件进行搜索和替换,并将所有 ENGINE=
实例替换为 engine_name
ENGINE=NDBCLUSTER
。如果您不想修改文件,可以使用未修改的文件创建表,然后使用 ALTER TABLE
更改其存储引擎。具体细节将在本节后面给出。
假设您已经在集群的 SQL 节点上创建了一个名为 world
的数据库,则可以使用 mysql 命令行客户端读取 city_table.sql
,并以通常的方式创建和填充相应的表
$> mysql world < city_table.sql
请务必牢记,前面的命令必须在运行 SQL 节点的 hosts 上执行(在本例中,是在 IP 地址为 198.51.100.20
的机器上)。
要在 SQL 节点上创建整个 world
数据库的副本,请在非集群服务器上使用 mysqldump 将数据库导出到名为 world.sql
的文件(例如,在 /tmp
目录中)。然后,修改表定义,如前所述,并将文件导入到集群的 SQL 节点,如下所示
$> mysql world < /tmp/world.sql
如果您将文件保存到其他位置,请相应地调整前面的说明。
在 SQL 节点上运行 SELECT
查询与在 MySQL 服务器的任何其他实例上运行它们没有什么不同。要从命令行运行查询,您首先需要以通常的方式登录到 MySQL Monitor(在 Enter password:
提示符处指定 root
密码)
$> 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.4.0-ndb-8.4.0
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql>
我们只使用 MySQL 服务器的 root
帐户,并假设您已遵循安装 MySQL 服务器的标准安全预防措施,包括设置强 root
密码。有关详细信息,请参阅 第 2.9.4 节 “保护初始 MySQL 帐户”。
值得注意的是,NDB 集群节点在相互访问时 不 使用 MySQL 权限系统。设置或更改 MySQL 用户帐户(包括 root
帐户)仅影响访问 SQL 节点的应用程序,不影响节点之间的交互。有关详细信息,请参阅 第 25.6.21.2 节 “NDB 集群和 MySQL 权限”。
如果您在导入 SQL 脚本之前没有修改表定义中的 ENGINE
子句,则此时应运行以下语句
mysql> USE world;
mysql> ALTER TABLE City ENGINE=NDBCLUSTER;
mysql> ALTER TABLE Country ENGINE=NDBCLUSTER;
mysql> ALTER TABLE CountryLanguage ENGINE=NDBCLUSTER;
选择数据库并针对该数据库中的表运行 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
$>
使用 MySQL 的应用程序可以使用标准 API 来访问 NDB
表。重要的是要记住,您的应用程序必须访问 SQL 节点,而不是管理节点或数据节点。这个简短的示例展示了我们如何使用在网络上其他地方的 Web 服务器上运行的 PHP 5.X mysqli
扩展来执行刚刚显示的 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 时一样。