【问题标题】:Neo4j: "ghost" node in label index throws errorNeo4j:标签索引中的“ghost”节点引发错误
【发布时间】:2014-12-11 15:36:06
【问题描述】:

我有一个 neo4j 数据库,其中包含一组带有标签的节点:EXAMPLE。

有两种操作。首先我删除一个节点,然后寻找另一个节点。它们是使用 neo4j API 单独完成的。

MATCH (n:EXAMPLE {Name: { name1 }}) DELETE n;

MATCH (n:EXAMPLE {Name: { name2 }}) RETURN n;

有时,当我执行第二个查询时,它会抛出一个错误“Node with id 123”。 ID 为 123 的节点是与在第一个查询中删除的相同节点。

当有大量请求同时进入数据库时​​会发生这种情况。


我猜如果节点被删除,但示例标签索引尚未更新,可能会发生这种情况。有两个事实证明了这种理论。

1) 错误不稳定。

2)如果我像这样更改第二个查询(删除标签),我不会收到错误:

MATCH (n {Name: { name2 }}) RETURN n;

Neo4j 版本为 2.1.5,Java - OpenJDK Runtime Environment (IcedTea 2.5.3) (7u71-2.5.3-2~deb7u1),操作系统为 Debian。数据库中除标签外没有其他索引。

问题是如何解决这个问题,但仍然使用标签?

【问题讨论】:

    标签: indexing neo4j label


    【解决方案1】:

    最终发生的是(简化的)操作将按如下顺序排列:

    Q1: MATCH (n)
    Q2: DELETE (n), COMMIT
    Q1: RETURN n # Error, n no longer exists
    

    出于实施原因,如果 cypher 是通过索引进行的,则更有可能发生这种情况。数据库最终会为您处理这个问题,但现在,您需要将该读取查询包装在一个重试块中 - 如果它因此类错误而失败,您只需再次运行它。

    关于这一点,还有其他可以通过重试轻松恢复的错误,例如死锁错误,因此将语句和/或事务包装在重试块中通常是一件有用的事情。

    【讨论】:

    • 这个解决方案看起来效率不高。重试块适用于连接错误,但不适用于数据库错误。数据库应该使用适当的锁在内部解决这种情况。
    • 顺便说一句,看起来你错了,我真正的问题是什么。简化后的顺序是:Q1: DELETE (n)Q2: MATCH (m) # Error, n no longer exists第二个查询中我没有寻找n,但它仍然保留在标签索引中,因此会引发错误。
    【解决方案2】:

    这是一种可能的解决方法:

    将节点标记为已删除而不是删除。忽略标记为已删除的节点。使用垃圾收集器一次性删除所有此类节点。

    【讨论】:

      猜你喜欢
      • 2022-12-11
      • 2016-12-21
      • 2013-05-25
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      • 2012-09-26
      • 2014-11-06
      相关资源
      最近更新 更多