gpt4 book ai didi

transactions - Neo4j 的密码交易是否被破坏?

转载 作者:行者123 更新时间:2023-12-03 12:00:11 25 4
gpt4 key购买 nike

TL;DR:我要么疯了,要么neo4j 的交易略有中断。看起来未提交的节点在已提交的事务之外可用,缺少属性 - 或者同样奇怪的东西。

我们的 node.js 应用程序使用 neo4j。其中一部分必须生成唯一的 ID。我们有以下密码查询,用于定位最后一个 :Id -type 节点并尝试提交一个新的 :Id具有 last_uuid+1 的节点.

MATCH (i:Id) WITH i ORDER BY i.uuid DESC LIMIT 1  #with it like a sub-return, will "run" the rest with the last i at read-time
CREATE (n:Id {label:"Test"})
SET n.uuid = i.uuid + 1
RETURN n

还有一个约束:
neo4j-sh (?)$ schema
Indexes
ON :Id(uuid) ONLINE (for uniqueness constraint)

Constraints
ON (id:Id) ASSERT id.uuid IS UNIQUE

数据库初始化为 (:Id{uuid:1})开始这种快乐。

应用程序代码基本上会重试上述查询,直到成功。如果同时命中两个或多个 Id 创建请求,则只有其中一个会通过,其余的将失败并由应用代码重试。

这很有效,直到我们并行尝试。

代码开始返回没有 uuid 的数据。经过大量调查,事实证明查询的写入部分(CREATE ...)以某种方式从没有 .uuid(或其他)属性的 MATCH 接收 :Id。这应该是不可能的。这是在这些节点上运行的唯一代码。

最奇怪(也许)的事情是,如果我保存 inodeid为了在数据库中定位该节点,它实际上存在并且具有 .uuid 属性。

为了隔离这种行为,我编写了一个 PoC: neo4j-transaction-test使用 nodejs 运行应该非常简单。

它基本上比上面的代码多一点 - 尝试创建 Id,设置 prev_label , prev_nodeid , 和 prev_uuid到前一个节点的 (i) 值。它针对在 localhost:9339 上收到的每个 GET 请求运行查询并输出:
 > node server.js 
* 1412125626667 Listening on 9339
Req Id | Datetime | -> $uuid $nodeid
1 1412125631677 'GET' # When it first receives the GET request
1 1412125631710 '->' 9 60 # When neo4j returns; numbers are $uuid $node_id)

当事情开始并发时,查询可能会失败:
3 1412125777096 '(retry) (0)' 'Node 64 already exists with label Id and property "uuid"=[13]'
4 1412125777098 '(retry) (0)' 'Node 64 already exists with label Id and property "uuid"=[13]'
de[]

这是意料之中的,它们被重试。如果我们以每秒几个请求( ab -n 1000 -c 10 http://localhost:9339/)“猛击”服务器,我们最终会看到:
...
59 1412127103011 'GET'
23 1412127103024 'ERROR - EMPTY UUID' '{"this_nodeid":22,"prev_nodeid":20,"label":"Test"}'

Error: Empty UUID received

(最终,我的意思是几乎立即)一个节点回来了,没有 uuid、prev_uuid 或 prev_label。 this_nodeid 和 prev_nodeid 指的是 neo4j 的内部 id。如果我们查找这些,从前一个 ( i) Id 节点开始(按 nodeid - 20):
neo4j-sh (?)$ match (i) where id(i)=20 return i;
+--------------------------------------------------------------------------------------------+
| i |
+--------------------------------------------------------------------------------------------+
| Node[20]{uuid:10,label:"Test",prev_label:"Test",prev_uuid:9,prev_nodeid:17,this_nodeid:20} |
+--------------------------------------------------------------------------------------------+
1 row
19 ms

这正是它应该的样子。 .uuid和所有。确实创建了新的,就像上面返回的一样:
neo4j-sh (?)$ match (i) where id(i)=22 return i;
+------------------------------------------------------+
| i |
+------------------------------------------------------+
| Node[22]{label:"Test",prev_nodeid:20,this_nodeid:22} |
+------------------------------------------------------+
1 row
17 ms

没有 prev_label 或 prev_uuid。这怎么可能?我错过了什么?是否有不完整的 :Id 节点泄漏到我的查询中?

我试过重启,删除数据目录,删除数据目录后重启,清理日志(没什么有趣的,甚至无聊,但在正确的时间 - 当上述情况发生时)。我现在正处于质疑我对这应该如何工作的理解的地步。

这是 12.04 和 neo4j 2.1.1。 More Version InfoNeo4j startup/shutdown logs .

我知道这不是创建 UUID 的最佳方式。这个问题是关于了解如果 neo4j 的事务按预期工作,这些结果是如何可能的。

最佳答案

我们在并发事务写入期间注意到 Neo4J 中的一个类似问题,并且在 Neo4J 2.2.5 中引入了一个修复程序来解决这个问题(我们有企业支持并提出了一个票来解决这个问题)。您可能没有完全相同的问题,但可能值得再次尝试使用 2.2.5 来查看它是否仍然是一个问题。

就像你说的,有更好的方法来生成 id。此外,您应该使用 MAX获取最新的而不是 LIMITORDER BY ,但这也不是重点;-)。

祝你好运。

关于transactions - Neo4j 的密码交易是否被破坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26133131/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com