并行运行时:参考

并行运行时在多个方面与槽式和流水线式运行时不同。本页解释了并行运行时的相关配置设置,以及它不受支持或被认为非线程安全的场景。本页还包含针对 Neo4j Aura 用户的相关信息。

不熟悉并行运行时的读者建议先阅读 并行运行时概念,然后再阅读本页。

更新查询

如果查询尝试更新图,并行运行时将抛出错误。例如,在并行运行时执行的任何使用 CREATE 子句的查询,都将抛出以下错误

错误信息
The parallel runtime does not support updating queries. Please use another runtime.

有关所有可用 Cypher® 写入子句的完整列表,请参见子句概述页面

事务

如果事务状态已发生更改,则无法使用并行运行时。

例如,以下事务(在 Cypher Shell 上启动)将被回滚,因为执行 Cypher 查询将更改事务的状态。

步骤 1:启动新事务并通过创建节点更改其状态
:begin
CREATE (n:Person)
步骤 2:尝试在现有事务上使用并行运行时执行 Cypher 查询
CYPHER runtime = parallel
RETURN 42
错误信息
An error occurred while in an open transaction. The transaction will be rolled back and terminated. Error: The parallel runtime is not supported if there are changes in the transaction state. Use another runtime.

有关 Neo4j 中事务的更多信息,请参见操作手册 → 事务管理

配置设置

可以配置以下设置来修改并行运行时的行为

表 1. server.cypher.parallel.worker_limit

描述

为并行运行时分配给 Cypher 工作线程的数量。如果设置为正数,将启动该数量的工作线程。如果设置为 0,则会为 Java 虚拟机可用的每个逻辑处理器启动一个工作线程。

如果设置为负数,我们将从可用逻辑处理器的数量中减去该值;例如,假设 Neo4j 在一台具有 16 个可用处理器的服务器上运行,使用 server.cypher.parallel.worker_limit = -1 则意味着有 15 个线程可用于并行运行时。

有效值

整数

默认值

0

server.cypher.parallel.worker_limit 设置为负数 -n(其中 n 大于总核心数)将禁用并行运行时。

有关 Neo4j 中配置设置的更多信息,请参见操作手册 → 配置

Aura

并行运行时适用于所有非免费的 AuraDB 实例,无论其大小或 CPU 数量如何。此外,当在 Aura 实例上使用并行运行时执行查询时,它可以利用多达所有可用的 CPU。

并行运行时在 AuraDB 免费实例上被禁用。尝试在 AuraDB 免费实例上使用并行运行时运行查询将抛出以下错误消息

错误信息
Parallel runtime has been disabled, please enable it or upgrade to a bigger Aura instance.

AuraDB Professional、AuraDB Business Critical 和 AuraDB Virtual Dedicated Cloud 的用户在创建实例时选择大小和可用 CPU 数量。有关 AuraDB 不同等级的更多信息,请参见Neo4j 定价页面

过程和函数

读取数据库的过程和函数受并行运行时支持。除此之外,在使用并行运行时时,需要注意两类过程和函数。

第一类可归类为更新过程。这些过程通过写入查询更新图,例如 Neo4j 过程 db.createLabeldb.createProperty。如果在并行运行时中调用的查询中包含此类过程,查询将失败。

第二类可归类为非线程安全的过程和函数。这些过程和函数执行的任务未受保护,以防止多个工作线程同时与目标数据交互。这包括执行以下任一任务的过程和函数

  • 执行 Cypher 查询(因为这将启动新事务,而并行运行时不支持新事务)。

  • 启动新事务(因为并行运行时不支持新事务)。

在并行运行时中调用的查询中包含执行这些任务的任何过程都不会使查询失败。相反,查询将自动在流水线运行时上运行。

Neo4j 过程

以下 Neo4j 过程不被认为是线程安全的,无法在并行运行时上运行。尝试在并行运行时中调用的查询中包含它们不会使查询失败。相反,查询将自动在流水线运行时上运行。

表 2. 非线程安全的 Neo4j 过程
过程

db.awaitIndex

db.awaitIndexes

db.checkpoint

db.info

db.labels

db.listLocks

db.ping

db.propertyKeys

db.prepareForReplanning

db.relationshipTypes

db.resampleIndex

db.resampleOutdatedIndexes

db.schema.nodeTypeProperties

db.schema.relTypeProperties

db.schema.visualization

dbms.checkConfigValue

dbms.listActiveLocks

dbms.listPools

dbms.scheduler.failedJobs

dbms.scheduler.groups

dbms.scheduler.jobs

dbms.upgrade

dbms.upgradeStatus

APOC

The APOC 库包含扩展 Cypher 用法的功能和过程。有许多 APOC 过程和函数不被认为是线程安全的,不能在并行运行时上运行。有关这些的更多信息,请参阅 APOC 手册中各个过程和函数的页面。

用户定义函数

用户定义函数是过程的简化形式,它们返回单个值且只读。要了解有关 Neo4j 中用户定义函数的更多信息,请参见Java 参考手册 → 用户定义函数

与 Neo4j 和 APOC 过程类似,任何通过执行 Cypher 查询来启动新事务的用户定义函数都不被认为是线程安全的,并且不受并行运行时支持(这包括所有用户定义的聚合函数)。

例如,考虑以下两个用户定义函数

class MyFunctions {
  @Context
  public Transaction transaction;

  @UserFunction("examples.return42")
  public long return42() {
    return 42L;
  }

  @UserFunction("examples.return42ViaCypher")
  public long return42ViaCypher() {
    return (long) transaction.execute("RETURN 42 AS res").next().get("n);
  }
}

运行 examples.return42() 在并行运行时下会成功,而 examples.return42ViaCypher() 将失败,因为执行新的 Cypher 查询会启动一个新事务。

但是,如果将 @NotThreadSafe 添加到方法中,则查询将自动不在并行运行时上运行。查询将转而默认在单线程流水线运行时上运行并生成通知。

因此,调用以下用户定义函数在并行运行时下不会失败。相反,Cypher 查询将自动在流水线运行时上运行。

class MyFunctions {
  @Context
  public Transaction transaction;

  @UserFunction("examples.return42ViaCypher")
  @NotThreadSafe
  public long return42ViaCypher() {
    return (long) transaction.execute("RETURN 42 AS res").next().get("n);
  }
}