错误处理

在运行数据库管理查询(例如 CREATE DATABASE)时,可能会遇到错误。

观察错误

由于数据库管理操作是异步执行的,因此这些错误可能不会在查询执行后立即返回。相反,您必须监控 SHOW DATABASE 命令的输出,特别是 statusMessagecurrentStatus 列。

创建数据库失败

neo4j@system> CREATE DATABASE foo;
0 rows available after 108 ms, consumed after another 0 ms
neo4j@system> SHOW DATABASE foo;

在单机模式下

+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| name   | type       | aliases | access       | address          | role      | writer | requestedStatus | currentStatus | statusMessage             | default | home  | constituents |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "foo"  | "standard" | []      | "read-write" | "localhost:7687" | "primary" | TRUE   | "online"        | "dirty"       | "File system permissions" | FALSE   | FALSE | []           |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 rows available after 4 ms, consumed after another 1 ms

在集群中

+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| name   | type       | aliases | access       | address          | role      | writer | requestedStatus | currentStatus | statusMessage             | default | home  | constituents |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "foo"  | "standard" | []      | "read-write" | "localhost:7687" | "primary" | TRUE   | "online"        | "online"      | ""                        | FALSE   | FALSE | []           |
| "foo"  | "standard" | []      | "read-write" | "localhost:7688" | "primary" | FALSE  | "online"        | "online"      | ""                        | FALSE   | FALSE | []           |
| "foo"  | "standard" | []      | "read-write" | "localhost:7689" | "primary" | FALSE  | "online"        | "dirty"       | "File system permissions" | FALSE   | FALSE | []           |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

3 row available after 100 ms, consumed after another 6 ms

数据库状态

数据库管理操作可能因多种原因而失败。例如,如果文件系统实例权限不正确,或者 Neo4j 本身配置错误。因此,SHOW DATABASE 查询结果中 statusMessage 列的内容可能会有很大差异。

但是,数据库只能处于少数几种特定状态之一:

  • online(在线)

  • offline(离线)

  • starting(正在启动)

  • stopping(正在停止)

  • store copying(存储复制中)

  • initial

  • deallocating(正在释放分配)

  • dirty(脏数据)

  • 已隔离 (quarantined)

  • unknown(未知)

有关各种状态的更多详细信息,请参阅 数据库状态。大多数情况下,当数据库管理操作失败时,Neo4j 会尝试将相关数据库转换为 offline(离线)状态。如果系统确定尚未创建任何存储文件,则会将数据库转换为 initial(初始)状态。同样,如果系统怀疑数据库底层的存储文件无效(不完整、已部分删除或损坏),则会将数据库转换为 dirty(脏数据)状态。

重试失败的操作

如果数据库管理操作失败,可以安全地进行重试。但是,这些重试并不保证成功,错误可能会在多次尝试后仍然存在。

如果数据库处于 quarantined(隔离)状态,则重试上一次操作将无效。

重试启动数据库

neo4j@system> START DATABASE foo;
0 rows available after 108 ms, consumed after another 0 ms
neo4j@system> SHOW DATABASE foo;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| name   | type       | aliases | access       | address          | role      | writer | requestedStatus | currentStatus | statusMessage             | default | home  | constituents |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "foo"  | "standard" | []      | "read-write" | "localhost:7687" | "primary" | TRUE   | "online"        | "offline"     | "File system permissions" | FALSE   | FALSE | []           |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 rows available after 4 ms, consumed after another 1 ms

在调查并解决底层问题后,您可以再次启动数据库并验证其是否正常运行。

neo4j@system> START DATABASE foo;
0 rows available after 108 ms, consumed after another 0 ms
neo4j@system> SHOW DATABASE foo;
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| name     | type       | aliases | access       | address          | role      | writer | requestedStatus | currentStatus | statusMessage | default | home  | constituents |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "foo"    | "standard" | []      | "read-write" | "localhost:7687" | "primary" | TRUE   | "online"        | "online"      | ""            | FALSE   | FALSE | []           |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 rows available after 4 ms, consumed after another 1 ms

如果反复重试命令无效,或者数据库处于 dirty(脏数据)状态,您可以删除并重新创建数据库,详情请参阅 创建数据库

在作为错误处理操作的一部分运行 DROP DATABASE 时,您还可以向命令追加 DUMP DATA。这将生成一个数据库转储文件,以便进一步检查并可能进行修复。

隔离的数据库

当数据库在正常运行期间遇到严重错误导致无法继续操作时,Neo4j 会停止该数据库并将其置于 quarantined(隔离)状态。这意味着无法通过简单的 START DATABASE 命令重新启动它。您必须运行 CALL dbms.unquarantineDatabase(server, database, operation) 来解除隔离,并指定包含故障数据库的 server(服务器)。

dbms.unquarantineDatabase() 过程在 Neo4j 2025.01 中引入,用于取代现已弃用的 dbms.quarantineDatabase()

解除隔离后,Neo4j 会自动尝试将数据库恢复到所需状态。

语法

CALL dbms.unquarantineDatabase(server, database, operation)

输入参数

名称 类型 描述

服务器 (server)

字符串

要解除数据库隔离的服务器标识符。

database

字符串

要放入隔离状态或从隔离状态中移除的数据库名称。

操作 (operation)

字符串

解除隔离时应用的可选操作。

可选操作的可能值包括:

  • keepStateKeepStore — 不做任何操作;保持存储和集群状态不变。

  • replaceStateKeepStore — 作为新成员加入,清除当前集群状态但保留存储。

  • replaceStateReplaceStore — 作为新成员加入,同时清除当前集群状态和存储。

如果您选择清除当前集群状态,则定义的数据库分配将尝试作为新成员加入。只有当大多数现有成员允许新成员加入时,此加入过程才能成功。假设您的数据库拓扑有三个主要分配。如果只有一个分配处于 quarantined(隔离)模式,则选择 replaceStateKeepStorereplaceStateReplaceStore 是安全的。如果有两个分配处于 quarantined(隔离)模式(意味着数据库在两台服务器上都被隔离),则不应同时对它们使用 replaceStateKeepStorereplaceStateReplaceStore,因为这样将没有多数派允许它们加入。

返回参数

该过程不返回任何值。

检查数据库是否被隔离
neo4j@system> SHOW DATABASE foo;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| name  | type       | aliases | access       | address          | role      | writer | requestedStatus | currentStatus | statusMessage                                           | default | home  | constituents |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "foo" | "standard" | []      | "read-write" | "localhost:7688" | "unknown" | FALSE  | "online"        | "quarantined" | "By neo4j at 2020-10-15T15:10:41.348Z: No reason given" | FALSE   | FALSE | []           |
| "foo" | "standard" | []      | "read-write" | "localhost:7689" | "primary" | FALSE  | "online"        | "online"      | ""                                                      | FALSE   | FALSE | []           |
| "foo" | "standard" | []      | "read-write" | "localhost:7687" | "primary" | TRUE   | "online"        | "online"      | ""                                                      | FALSE   | FALSE | []           |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

3 row available after 100 ms, consumed after another 6 ms

用户数据库的 quarantined(隔离)状态是持久化的。这意味着如果数据库被隔离,即使重启 Neo4j 进程,它仍将保持隔离状态。您只能通过运行 dbms.unquarantineDatabase() 过程来移除 quarantined(隔离)状态。

此规则的唯一例外是 system 数据库。针对该数据库的任何隔离都会在 Neo4j 进程重启后自动移除。