常见问题与故障排除

常规问题

该软件与 Morpheus 或 Cypher for Apache Spark (CAPS) 有关联吗?

没有。两者之间没有任何共享的代码或方法,并且它们采用的方法截然不同。Cypher® for Apache Spark/Morpheus 采取的方法是在 Spark 环境中提供一个可以执行 Cypher 查询的解释器,并为 Spark 提供原生图表示。相比之下,本连接器不提供该功能,而是专注于在 Neo4j 和 Spark 之间进行数据的读写操作。通过此连接器,所有 Cypher 代码严格在 Neo4j 内部执行。Spark 环境像往常一样基于 DataFrame 进行操作,此连接器不为 Spark 提供图 API 原语。

如何加快向 Neo4j 的写入速度?

Spark 连接器本质上是以批处理方式将数据写入 Neo4j 的。Neo4j 是一个事务型数据库,所有的修改都在事务中完成。而这些事务本身是有开销的。

提高写入性能的最简单方法如下:

  • 您可以增加批处理大小(选项 batch.size)。批次越大,写入所有数据所需执行的事务就越少,产生的事务开销也就越少。

  • 确保您的 Neo4j 实例拥有充足的可用堆内存和大小合适的页面缓存(page cache)。堆内存太小会导致无法提交大批次数据,从而减慢整体导入速度。

为了获得最佳性能,请确保您熟悉 Operations manual(操作手册)中的内容。

请务必记住,Neo4j 的写入是垂直扩展的,而读取是水平扩展的。在 Causal Cluster Model(因果集群模型)中,只有集群领导者(1 台机器)可以接受写入。因此,为了最大化写入吞吐量,请专注于提升集群领导者的硬件配置和性能。

为什么返回的列顺序与我在查询中指定的顺序不一致?

遗憾的是,这是一个已知问题,存在于 Neo4j 3.x 和 Neo4j 4.0 版本中。从 Neo4j 4.1 开始,您将获得与 return 语句中指定的相同顺序。

我该从哪里获得帮助?

Neo4j 社区网站是一个提问、与使用该连接器的其他用户交流以及从 Neo4j 专家处获取帮助的好地方。您也可以在 Neo4j Discord 频道中留言。

错误

我的写入因死锁异常(Deadlock Exceptions)而失败,我该怎么办?

在某些情况下,Neo4j 会因为您可能在堆栈跟踪中看到的死锁异常而拒绝写入事务。

这篇 Neo4j 知识库文章描述了该问题。

通常这是由于向 Neo4j 写入时的并行度过高导致的。例如,当您写入关系 (:A)-[:REL]→(:B) 时,这会在数据库中对两个节点创建“锁”。如果其他并发线程过于频繁地尝试写入这些节点,可能会导致死锁异常并使事务失败。

通常,解决方案是在写入 Neo4j 之前对 DataFrame 进行重新分区(repartition),以避免多个分区写入同时锁定相同的节点和关系。

我遇到了类似 UTF8String cannot be cast to Long 的类型转换错误。有什么解决方案?

您可能会遇到类似以下的错误,或者是不同类型的错误:

java.lang.ClassCastException: org.apache.spark.unsafe.types.UTF8String cannot be cast to java.lang.Long

这通常是因为同一个节点标签上的某个字段具有不同的类型。您可以通过安装 APOC 来解决此问题:这消除了错误,但该字段的所有值都会被强制转换为 String 类型。发生这种情况的原因是 Spark 不是无模式(schema-free)的,它要求每一列必须始终具有其固定的类型。

您可以在此处阅读更多内容。

我遇到了 TableProvider implementation org.neo4j.spark.DataSource cannot be written with ErrorIfExists mode, please use Append or Overwrite modes instead 的错误。我该怎么办?

如果您在尝试向 Neo4j 写入时遇到此错误,请注意,当前版本的连接器不支持 Spark 3 上的 SaveMode.ErrorIfExists,而这是默认的保存模式。因此,请将保存模式更改为 SaveMode.AppendSaveMode.Overwrite 中的一种。

我们正在努力在 Spark 3 上完全支持所有的保存模式。

我遇到了 NoClassDefFoundErrorClassNotFoundException 错误。我该怎么办?

您可能会遇到以下类型的错误之一:

NoClassDefFoundError: org/apache/spark/sql/sources/v2/ReadSupport
Caused by: ClassNotFoundException: org.apache.spark.sql.sources.v2.ReadSupport
java.lang.NoClassDefFoundError: scala/collection/IterableOnce
Caused by: java.lang.ClassNotFoundException: scala.collection.IterableOnce

这意味着您的 Spark 版本与连接器上的 Spark 版本不匹配。请参考此页面了解您需要哪个版本。

我遇到了 Failed to invoke procedure gds.graph.create.cypher: Caused by: java.lang.IllegalArgumentException: A graph with name [name] already exists 的错误。我该怎么办?

在使用 GDS 库创建新图时可能会发生这种情况。问题在于查询被执行了两次:第一次是为了提取 DataFrame 的模式(schema),第二次是为了获取数据。

为避免此问题,您可以使用用户定义模式(user defined schema)的方法。

Databricks 设置

连接到 Aura 时我遇到了 SSL 握手错误。

由于 Databricks 的自定义 Java 安全设置移除了对某些加密密码的支持,从 Databricks 连接的 Aura 客户可能会遇到 SSL 握手错误。

有关详细信息,请参阅 Aura 支持文章:Connecting to Aura with Databricks

故障排除

如何获取底层的 Neo4j 驱动程序调试日志?

这仅适用于 Spark 连接器 4.1.4 及更高版本。

Spark 程序需要按照 Spark 手册中的说明进行日志记录配置。

org.neo4j.driver 包的级别设置为 TRACE,并将 org.neo4j.driver.internal.shaded 下包的级别设置为 WARNERROR

随后将出现类似于以下的日志消息,提供有关 Neo4j Bolt 服务器与 Spark 连接器 Neo4j 驱动程序之间 Bolt 交换的详细视图(格式可能会根据您的日志记录配置而有所不同)

2025-06-23 16:32:22 INFO  org.neo4j.driver.internal.DriverFactory:41 - Direct driver instance 584203303 created for server address localhost:63380
2025-06-23 16:32:22 TRACE org.neo4j.driver.internal.async.pool.ConnectionPoolImpl:76 - Acquiring a connection from pool towards localhost:63380
2025-06-23 16:32:22 TRACE org.neo4j.driver.internal.async.connection.ChannelConnectedListener:76 - [0x6651d7e4][localhost:63380][] Channel [id: 0x6651d7e4, L:/127.0.0.1:63395 - R:localhost/127.0.0.1:63380] connected, initiating bolt handshake
2025-06-23 16:32:22 DEBUG org.neo4j.driver.internal.async.connection.ChannelConnectedListener:62 - [0x6651d7e4][localhost:63380][] C: [Bolt Handshake] [0x6060b017, 132100, 260, 4, 3]
2025-06-23 16:32:22 DEBUG org.neo4j.driver.internal.async.connection.HandshakeHandler:62 - [0x6651d7e4][localhost:63380][] S: [Bolt Handshake] 4.4