管理集群中的数据库

创建数据库或在创建后修改数据库时,您可以设置托管数据库的主服务器和辅助服务器的数量。要指定初始拓扑,请使用命令 CREATE DATABASE。要在数据库创建后更改拓扑,请运行 ALTER DATABASE 命令。如果不再需要某个数据库,命令 DROP DATABASE 会从集群中删除该数据库。

CREATE DATABASE

在集群中创建数据库的命令与在非集群环境中创建数据库的命令没有显著区别(有关单个服务器上的数据库管理信息,请参阅创建、启动和停止数据库)。集群环境中的区别在于可以指定拓扑,即数据库所需的主服务器和辅助服务器的数量。要创建数据库 foo,其中 3 个服务器以主模式托管数据库,2 个服务器以辅助模式托管数据库,请运行以下命令:

CREATE DATABASE foo TOPOLOGY 3 PRIMARIES 2 SECONDARIES

或者,您可以使用参数来提供主服务器和辅助服务器的数量

参数
{
  "dbname": "foo",
  "primary": 3,
  "secondary": 2
}
查询
CREATE DATABASE $dbname TOPOLOGY $primary PRIMARIES $secondary SECONDARIES

只有当集群的服务器能够满足指定的拓扑时,该命令才能成功执行。如果不能,该命令将导致错误。例如,如果集群的服务器设置了模式约束,只能包含两个主服务器和三个辅助服务器,或者只有四个服务器存在,该命令将失败并报错。

如果未指定 TOPOLOGY,则数据库将根据 neo4j.conf 中指定的 initial.dbms.default_primaries_countinitial.dbms.default_secondaries_count 创建。集群启动后,您可以使用 dbms.setDefaultAllocationNumbers 过程覆盖这些值。

CREATE DATABASE 命令会分配数据库,因此无需执行 REALLOCATE DATABASES(在在添加的服务器上托管数据库中描述)。

但是,随着时间的推移,或者在执行了多个 CREATE DATABASE 命令后,数据库的分布可能会变得不平衡。此时,您可以运行 REALLOCATE DATABASES 命令,使集群在集群中的所有服务器之间重新平衡数据库。

ALTER DATABASE

要在数据库创建后更改其拓扑或读/写访问权限,请使用 ALTER DATABASE 命令。

修改数据库拓扑

要更改上一个示例中数据库 foo 的拓扑,请运行以下命令:

ALTER DATABASE foo SET TOPOLOGY 2 PRIMARIES 1 SECONDARY

或者,您可以使用参数来提供主服务器和辅助服务器的数量

参数
{
  "dbname": "foo",
  "primary": 2,
  "secondary": 1
}
查询
ALTER DATABASE $dbname SET TOPOLOGY $primary PRIMARIES $secondary SECONDARIES

CREATE DATABASE 命令一样,如果集群不包含足够的服务器来满足请求的拓扑,此命令将导致错误。

此外,ALTER DATABASE 命令是可选幂等的,如果数据库不存在也会导致错误。可以附加 IF EXISTS 命令以确保如果数据库不存在,则不会返回错误。

当指定拓扑存在多种可能的排列时,Neo4j 使用分配器来决定如何将数据库分布到集群中。请注意,与 CREATE DATABASE 一样,ALTER DATABASE 命令会分配数据库,并且除非希望在集群中的所有服务器之间重新平衡数据库,否则无需执行 REALLOCATE DATABASES

这通常发生在集群配置的服务器数量多于任何一个数据库的主服务器和辅助服务器总和时。

无法自动转换为只有一个主机的拓扑。尝试这样做将导致错误。

但是,可以手动执行此转换:

  1. 第一步是备份数据库,有关更多信息,请参阅备份与恢复

  2. 数据库备份完成后,下一步是删除数据库。有关更多详细信息,请参阅删除数据库

  3. 最后一步是使用新拓扑从备份中初始化集群,或将备份恢复到单个服务器上。有关初始化的信息,请参阅后面的初始化集群

此外,也可以自动从只有一个主机的拓扑转换为多个主机的拓扑。请记住,在这样的转换过程中,数据库会暂时不可用。

如果 ALTER DATABASE 命令减少了数据库的分配数量,则会首先删除隔离服务器上的分配。

查询
ALTER DATABASE nonExisting IF EXISTS SET TOPOLOGY 1 PRIMARY 0 SECONDARY

修改数据库访问权限

要修改数据库 foo 的访问权限,语法如下:

ALTER DATABASE foo SET ACCESS {READ ONLY | READ WRITE}

默认情况下,新创建的数据库同时具有读写访问权限。

解除数据库分配

为了减轻特定服务器的负载,您可以使用以下过程之一来解除数据库在导致压力的服务器上的分配:

您必须拥有 SERVER MANAGEMENT 权限才能执行这些过程。

例如,server01 托管了两个小型数据库 foobar,以及一个非常大的数据库 baz,而其他服务器包含的数据库较少或较小,并且 server01 负载很高。

您可以使用以下方法之一,从 server01 解除 baz 数据库的分配,或从 server01 解除多个数据库的分配:

从服务器解除数据库分配
// With dry run
neo4j@system> CALL dbms.cluster.deallocateDatabaseFromServer("server01", "baz", true);

// Without dry run
neo4j@system> CALL dbms.cluster.deallocateDatabaseFromServer("server01", "baz");
从多个服务器解除数据库分配
// With dry run
neo4j@system> CALL dbms.cluster.deallocateDatabaseFromServers(["server01", "server02"], "baz", true);

// Without dry run
neo4j@system> CALL dbms.cluster.deallocateDatabaseFromServers(["server01", "server02"], "baz");
从服务器解除三个数据库的分配
// With dry run
neo4j@system> CALL dbms.cluster.deallocateNumberOfDatabases("server01", 3, true);

// Without dry run
neo4j@system> CALL dbms.cluster.deallocateNumberOfDatabases("server01", 3);

重新分配数据库

为了重新平衡集群中所有数据库的分配,例如,因为您添加了新服务器,请使用过程或 Cypher 命令将数据库重新分配到新服务器上。

使用过程重新分配数据库

您可以使用过程 dbms.cluster.reallocateDatabase 来重新平衡集群中的特定数据库,或者使用 dbms.cluster.reallocateNumberOfDatabases 来重新平衡集群中多个数据库的分配并减轻过载服务器的压力。请注意,如果集群已平衡,运行这些过程时不会发生重新分配。这些过程不需要服务器名称,并且可以在有或没有试运行的情况下执行。

您必须拥有 SERVER MANAGEMENT 权限才能执行这些过程。

例如,您添加了三台新服务器,并希望将一个非常大的数据库 baz 从所有包含它的服务器移动到新服务器上。

将一个数据库重新分配到新服务器
// With dry run
neo4j@system> CALL dbms.cluster.reallocateDatabase("baz", true);

// Without dry run
neo4j@system> CALL dbms.cluster.reallocateDatabase("baz");
将多个数据库重新分配到新服务器
// With dry run
neo4j@system> CALL dbms.cluster.reallocateNumberOfDatabases(3, true);

// Without dry run
neo4j@system> CALL dbms.cluster.reallocateNumberOfDatabases(3);

使用 Cypher 命令重新分配数据库

您可以使用 Cypher 命令 REALLOCATE DATABASES 来重新平衡集群中所有数据库的分配并减轻过载服务器的压力。此命令也可以与 DRYRUN 一起使用,以预览新的数据库分配。

在包含许多数据库的大型集群上执行 REALLOCATE DATABASES 可能会一次性移动大量分配,这可能会给集群带来压力。建议从更有限的重新分配开始,例如使用较小数目的 dbms.cluster.reallocateNumberOfDatabases,并让数据库完成其重新分配,然后再再次调用,直到不再需要重新分配为止。

neo4j@neo4j> DRYRUN REALLOCATE DATABASES;
+----------------------------------------------------------------------------------------------------------------------------------------+
| database | fromServerName | fromServerId                           | toServerName | toServerId                             | mode      |
+----------------------------------------------------------------------------------------------------------------------------------------+
| "bar"    | "server-1"     | "00000000-27e1-402b-be79-d28047a9418a" | "server-5"   | "00000003-b76c-483f-b2ca-935a1a28f3db" | "primary" |
| "bar"    | "server-3"     | "00000001-7a21-4780-bb83-cee4726cb318" | "server-4"   | "00000002-14b5-4d4c-ae62-56845797661a" | "primary" |
+----------------------------------------------------------------------------------------------------------------------------------------+

初始化集群

有两种不同的方法来初始化集群数据:

  • 第一种选择是使用“指定初始化器”,即使用指定服务器在集群中的其他服务器上创建已备份的数据库。

  • 另一种选择是从 URI 初始化集群,其中所有托管数据库的服务器都使用该 URI 指定的外部源提供的相同种子进行初始化。有关更多详细信息,请参阅从 URI 创建数据库

请记住,在某些情况下使用指定初始化器可能会有问题,因为无法预先知道数据库将如何分配给集群中的服务器。此外,此方法依赖于种子已存在于其中一台服务器上。

指定初始化器

为了将集群中的服务器指定为初始化器,使用 neo4j-admin database restore 命令将数据库备份传输到该服务器。随后,该服务器将用作其他集群成员复制已备份数据库的源。

此示例创建了一个名为 foo 的用户数据库,它托管在三台主模式服务器上。foo 数据库之前不应存在于集群中的任何服务器上。

如果已存在与备份同名的数据库,请使用命令 DROP DATABASE 删除它以及所有与其关联的用户和角色。

  1. 在一台服务器上恢复 foo 数据库。在此示例中,使用了 server01 成员。

    bin/neo4j-admin database restore --from-path=/path/to/foo-backup-dir foo
  2. 通过登录 Cypher Shell 并运行 SHOW SERVERS 找到 server01 的服务器 ID。交叉引用地址以找到服务器 ID。使用任何数据库进行连接。

    SHOW SERVERS YIELD serverId, name, address, state, health, hosting;
    +-----------------------------------------------------------------------------------------------------------------------------------------------------+
    | serverId                               | name                                   | address          | state     | health      | hosting              |
    +-----------------------------------------------------------------------------------------------------------------------------------------------------+
    | "25a7efc7-d063-44b8-bdee-f23357f89f01" | "25a7efc7-d063-44b8-bdee-f23357f89f01" | "localhost:7689" | "Enabled" | "Available" | ["system",  "neo4j"] |
    | "782f0ee2-5474-4250-b905-4cd8b8f586ba" | "782f0ee2-5474-4250-b905-4cd8b8f586ba" | "localhost:7688" | "Enabled" | "Available" | ["system",  "neo4j"] |
    | "8512c9b9-d9e8-48e6-b037-b15b0004ca18" | "8512c9b9-d9e8-48e6-b037-b15b0004ca18" | "localhost:7687" | "Enabled" | "Available" | ["system",  "neo4j"] |
    +-----------------------------------------------------------------------------------------------------------------------------------------------------+

    在此示例中,server01 的地址是 localhost:7687,因此服务器 ID 是 8512c9b9-d9e8-48e6-b037-b15b0004ca18

  3. 在其中一台服务器上,使用 system 数据库并使用 server01 的服务器 ID 创建数据库 foofoo 的拓扑存储在 system 数据库中,当您创建它时,它会根据默认拓扑进行分配(可以通过 CALL dbms.showTopologyGraphConfig 显示)。这可能与 foo 备份时的拓扑不同。如果您想确保集群中的特定分配,可以在 CREATE DATABASE 命令中使用 TOPOLOGY 子句指定所需的拓扑。有关更多信息,请参阅CREATE DATABASE

    CREATE DATABASE foo
    TOPOLOGY [desired number of primaries] PRIMARIES [desired number of secondaries] SECONDARIES
    OPTIONS {existingData: 'use', existingDataSeedServer: '8512c9b9-d9e8-48e6-b037-b15b0004ca18'};
  4. 验证 foo 数据库是否在所需数量的服务器上以所需角色在线。如果 foo 数据库的规模较大,命令的执行可能需要一些时间。

    SHOW DATABASE foo;
    +------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | name  | type       | aliases | access       | address          | role      | writer | requestedStatus | currentStatus | statusMessage | default | home  | constituents |
    +------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | "foo" | "standard" | []      | "read-write" | "localhost:7687" | "primary" | FALSE  | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    | "foo" | "standard" | []      | "read-write" | "localhost:7688" | "primary" | FALSE  | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    | "foo" | "standard" | []      | "read-write" | "localhost:7689" | "primary" | TRUE   | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
    +------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    
    9 rows available after 3 ms, consumed after another 1 ms

使用允许/拒绝的数据库控制位置

数据库默认可以分配到集群中的任何服务器上运行。但是,可以限制特定数据库托管的服务器。这通过 ENABLE SERVERALTER SERVER 完成,如管理集群中的服务器中所述。以下选项可用:

  • allowedDatabases - 允许在服务器上托管的数据库集合。

  • deniedDatabases - 禁止在服务器上托管的数据库集合。允许和禁止是互斥的。

  • modeConstraint - 控制数据库可以在服务器上以何种模式(主、辅助或无)托管。如果未设置,则服务器上没有模式约束。

更改默认数据库

您可以使用过程 dbms.setDefaultDatabase("newDefaultDatabaseName") 来更改 DBMS 的默认数据库。从 Neo4j 2025.04 开始,默认数据库也可以设置为本地或远程数据库别名。

  1. 确保要设置为默认的数据库存在,否则使用命令 CREATE DATABASE <database-name> 创建它。

  2. 使用命令 SHOW DEFAULT DATABASE 显示当前默认数据库的名称和状态。

  3. 使用命令 STOP DATABASE <database-name> 停止当前默认数据库。

  4. system 数据库运行 CALL dbms.setDefaultDatabase("newDefaultDatabaseName") 以设置新的默认数据库。

  5. 可选地,您可以使用 START DATABASE <database-name> 将之前的默认数据库作为非默认数据库启动。

请注意,自动创建的初始默认数据库的拓扑可能与默认配置值不同。有关更多信息,请参阅集群中的默认数据库

错误处理

数据库可能会进入错误状态。通常您可以使用 SHOW DATABASES 命令观察到这一点,并使用错误处理指南寻求帮助。

在更严重的情况下,您可能正在处理灾难情况,其中整个 DBMS 可能无法正常响应,或者某些特定数据库无法在不中断服务的情况下恢复。有关这些情况,请参阅灾难恢复指南

© . All rights reserved.