Neo4j 2.0唯一约束错误“节点已存在”,但实际上不存在该节点。

16

我在使用neo4j的唯一约束时遇到了一些麻烦,因为创建一个cypher语句由于节点已经存在而无法执行。问题是,它并不存在。而且,这个过程和数据昨天完全相同,昨天还可以正常工作。

我的neo4j版本是社区版2.0.0(发布版),在ubuntu 12.04.3上运行。这是我的当前情况:

我的约束条件:

tas@vtas:~$ neo4j-shell
neo4j-sh (?)$ schema
Indexes
  ON :ConsumerUser(tokens) ONLINE
  ON :Id(uuid)             ONLINE (for uniqueness constraint) #relevant
  ON :User(email)          ONLINE (for uniqueness constraint)
  ON :User(username)       ONLINE (for uniqueness constraint) 

Constraints
  ON (user:User) ASSERT user.email IS UNIQUE
  ON (user:User) ASSERT user.username IS UNIQUE
  ON (id:Id) ASSERT id.uuid IS UNIQUE                         #relevant

Id.uuid 应该是唯一的。

我没有任何数据:

neo4j-sh (?)$ dump
begin
create index on :`ConsumerUser`(`tokens`);
create index on :`Id`(`uuid`);
create index on :`User`(`email`);
create index on :`User`(`username`);
;

(还可以通过Cypher MATCH (n) RETURN n;进行验证)

问题查询:

neo4j-sh (?)$ cypher 2.0 CREATE (i:Id{uuid:2});
CypherExecutionException: Node 82 already exists with label Id and property "uuid"=[2]

我尝试过的事情

  • tail -f /var/lib/neo4j/data/log/*.log /var/lib/neo4j/data/graph.db/*.log /var/log/neo4j/*.log 查找错误:没有任何日志记录
  • 重启 neo4j (service neo4j-service restart)
  • 在重启过程中执行上述 tail 命令(唯一有趣的行是:[main] INFO org.neo4j.kernel.AutoConfigurator - WARNING! Physical memory(1017MB) is less than assigned JVM memory(4185MB). Continuing but with available JVM memory set to available physical memory
  • 删除索引 (/var/lib/neo4j/data/graph.db/index/ 和 /var/lib/neo4j/data/graph.db/index.db),然后重新启动
  • 恢复上述内容,重新启动
  • 在 Stack Overflow 上搜索
  • 在 neo4j 的 Github 问题页上搜索

到目前为止,没有任何帮助。

我不会尝试的事情

  • 这里的解决方案:neo4j constraint deleted node,因为在生产环境中放弃约束条件并不是一个选项。而且,那是几个版本之前,也是不同的用例:
    1. String[] 进行约束而不是 Int
    2. 有日志被记录
  • 在不知道是否已明确解决此问题的情况下,以交叉手指的方式升级到 2.0.1(我需要知道为什么会发生这种情况)

其他信息

  • 我将 ulimit -nulimit -Hn 设置为 40K

  • neo4j-sh (?)$ dbinfo -g Kernel

{
  "KernelStartTime": "Fri Feb 21 13:53:57 GMT 2014",
  "KernelVersion": "Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.0.0",
  "MBeanQuery": "org.neo4j:instance=kernel#0,name=*",
  "ReadOnly": false,
  "StoreCreationDate": "Fri Feb 14 18:43:27 GMT 2014",
  "StoreDirectory": "/var/lib/neo4j/data/graph.db",
  "StoreId": "a3351846c194229c",
  "StoreLogVersion": 21
}
  • 我看到过这个:https://github.com/neo4j/neo4j/issues/1069,但它似乎已经解决了。

  • 这是在MacOSX 10.6主机上的VirtualBox虚拟机中。

  • 我不知道该怎么办了,只好来SO发第一个问题。

    简单的答案是“把所有东西都清除然后重新开始”(或者重新做约束),但这并不是真正可接受的(如果这在生产环境中发生会怎样?)。

    有什么想法吗?


    你可以尝试使用Cypher的MERGE命令吗?基本上它会避免出现异常,因为MERGE要么创建一个节点模式,要么返回一个已存在的节点模式。 - Sumeet Sharma
    1
    neo4j-sh (?)$ MERGE (i:Id{uuid:2});EntityNotFoundException: Node with id 82 - Tasos Bitsios
    1
    相同。neo4j-sh (?)$ start n = node(82) return n; EntityNotFoundException: 找不到ID为82的节点 - Tasos Bitsios
    有任何想法是怎么发生的吗?它在启动/重新启动期间应该自行修复,还是有一个单独的工具可以做到这一点,我在谷歌上没有找到?(我不介意这个特定的开发实例,只是担心这种情况在生产中发生) - Tasos Bitsios
    它发生在我刚开始使用neo4j的时候。当neo4j服务器突然停止或由于某些原因事务未能正确完成或数据库未能正确关闭时。虽然我不确定根本原因是什么。 - Sumeet Sharma
    显示剩余6条评论
    1个回答

    4
    您的数据库已经损坏。Neo4j内部引用了这个节点,但是您却删除了该节点,因此该引用指向了一个不存在的位置。您无法删除它,因为它不存在,也无法创建它,因为它认为它已经存在了。(这很可能是由于数据库意外关闭导致的。请确保在生产中使用的计算机具有电池备份)
    这就是为什么您总是要在生产环境中备份数据!如果某个分片损坏了,那么您只需清除它并重新加载数据即可。最小化停机时间,无需了解它是如何损坏的,只需要知道它已经损坏了。如果您没有备份(您应该有离线备份),那么您需要将数据导出到CSV文件,清除数据库,并重新加载CSV数据。清除数据库指的是完全删除旧的数据库目录,让Neo4j创建一个新的数据库。
    (不要试图在进行干净的清除之前挽救数据库,因为一旦数据库损坏,您就无法知道它被破坏的方式和程度。)

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接