错误处理

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

观察错误

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

示例 1. 无法创建数据库
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 列的内容可能会有很大差异。

但是,数据库可能只处于以下几种状态之一

  • 在线

  • 离线

  • 启动中

  • 停止中

  • 存储复制

  • 初始

  • 释放中

  • 隔离

  • 未知

有关各种状态的更多详细信息,请参阅 数据库状态。大多数情况下,当数据库管理操作失败时,Neo4j 会尝试将目标数据库转换为 offline 状态。如果系统确定尚未创建任何存储文件,则它会改为将数据库转换为 initial 状态。类似地,如果系统怀疑数据库的基础存储文件无效(不完整、部分删除或损坏),则它会将数据库转换为 dirty 状态。

重试失败的操作

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

如果数据库处于 quarantined 状态,则重试上次操作将不起作用。

示例 2. 重试启动数据库
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追加到命令中。它会生成一个数据库转储,可以进一步检查并可能修复。

隔离数据库

有两种方法可以将数据库置于quarantined状态

  • 使用dbms.quarantineDatabase过程在本地隔离特定数据库。该过程必须在您要隔离其数据库副本的实例上执行。例如,当数据库由于数据库所在的卷的系统文件权限问题无法在给定实例上启动时,或者当最近启动的数据库开始记录错误时,就需要执行此操作。隔离状态会使数据库在该实例上不可访问,并阻止其状态被更改,例如使用START DATABASE命令。

    如果在集群中运行,数据库管理命令(例如START DATABASE foo)仍将在隔离foo的实例上生效。

  • 当数据库在其正常运行期间遇到严重错误,导致其无法进一步操作时,Neo4j 会停止该数据库并将其置于quarantined状态。这意味着无法通过简单的START DATABASE命令重新启动它。您必须在包含故障数据库的实例上执行CALL dbms.quarantineDatabase(databaseName, false)才能解除隔离。

解除隔离后,实例会自动尝试将数据库置于所需状态。

建议通过bolt://协议而不是neo4j://协议运行隔离过程,因为后者可能会将请求路由到意外实例。

语法

CALL dbms.quarantineDatabase(databaseName,setStatus,reason)

参数

名称 类型 描述

databaseName

String

将被隔离或解除隔离的数据库的名称。

setStatus

Boolean

true表示将数据库置于隔离状态;false表示解除隔离。

reason

String

(可选) 将数据库置于隔离状态的原因。

返回值

名称 类型 描述

databaseName

String

数据库的名称。

隔离

String

实际状态。

result

String

上次操作的结果。结果包含用户、时间和隔离原因。

dbms.quarantineDatabase过程替换了dbms.cluster.quarantineDatabase,后者已在 Neo4j 4.3 中弃用,将在下一个主要版本中删除。

隔离数据库
neo4j@system> CALL dbms.quarantineDatabase("foo",true);
+--------------------------------------------------------------------------------------+
| databaseName | quarantined | result                                                  |
+--------------------------------------------------------------------------------------+
| "foo"        | TRUE        | "By neo4j at 2020-10-15T15:10:41.348Z: No reason given" |
+--------------------------------------------------------------------------------------+

3 row available after 100 ms, consumed after another 6 ms
检查数据库是否被隔离
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.quarantineDatabase过程,并将setStatus参数设置为false来解除隔离。

此规则的唯一例外是内置system数据库。对该数据库的任何隔离都会在实例重新启动后自动解除。