Neo4j/Cypher在高度并发的环境中创建独特的关系
对于给定的关系类型,我需要有某种唯一的约束Neo4j/Cypher在高度并发的环境中创建独特的关系,neo4j,cypher,graph-databases,nosql,Neo4j,Cypher,Graph Databases,Nosql,对于给定的关系类型,我需要有某种唯一的约束 (a)-[:RELATION]->(b) 为了实现这一点,我正在使用createunique(a)-[:RELATION]->(b) 在并发环境中,如果多个线程可以在相同的节点之间创建(a)-[:RELATION]->(b),我将得到UniquePathNotUniqueException,以及由于neo4j事务隔离的性质而创建的多个关系 我发现目前创建唯一关系的唯一方法是写锁两个节点 有没有其他方法可以保证建立独一无二的关系 更新 这就是我最
(a)-[:RELATION]->(b)
为了实现这一点,我正在使用createunique(a)-[:RELATION]->(b)
在并发环境中,如果多个线程可以在相同的节点之间创建(a)-[:RELATION]->(b)
,我将得到UniquePathNotUniqueException
,以及由于neo4j事务隔离的性质而创建的多个关系
我发现目前创建唯一关系的唯一方法是写锁两个节点
有没有其他方法可以保证建立独一无二的关系
更新
这就是我最后使用的方法
MATCH (a), (b)
SET a._lock_ = true, b._lock_ = true
MERGE (a)-[:RELATION]->(b)
REMOVE a._lock_, b._lock_
MATCH (a), (b)
SET a._lock_ = true, b._lock_ = true
MERGE (a)-[:RELATION]->(b)
REMOVE a._lock_, b._lock_
使用额外的重试循环和指数回退过程,可能会出现死锁。您需要对关系使用
合并
,但事先需要获取锁以防止并发问题。作为移除不存在的属性的副作用,这是最容易做到的:
MATCH (a:Label{key:value}), (b:Label{key:value2})
REMOVE a._non_existing_property, b._non_existing_property
MERGE (a)-[:RELATION]->(b)
更新
我上面的陈述有死锁的危险(Neo4j将检测并优雅地处理死锁)。为防止必须以一致的顺序(例如,通过较小的节点id)获取锁:
MATCH (a:Label{key:value}), (b:Label{key:value2})
WITH a, b, case when id(a) < id(b) then a else b end as locknode
REMOVE locknode._non_existing_property
MERGE (a)-[:RELATION]->(b)
MATCH(a:Label{key:value}),(b:Label{key:value2})
对于a、b,当id(a)(b)
这就是我在最后使用的方法
MATCH (a), (b)
SET a._lock_ = true, b._lock_ = true
MERGE (a)-[:RELATION]->(b)
REMOVE a._lock_, b._lock_
MATCH (a), (b)
SET a._lock_ = true, b._lock_ = true
MERGE (a)-[:RELATION]->(b)
REMOVE a._lock_, b._lock_
使用额外的重试循环和指数回退来处理可能的死锁。您是否尝试了
MERGE(a)-[:RELATION]->(b)
?我认为应该隐式地处理写锁。merge不能保证唯一性doa
和b
已经存在于图形中,并且您正在匹配它们?如果是这样的话,我很确定在这种情况下,MERGE
将在它们上获取一个写锁。这两个节点都已经存在<代码>合并不接受写锁,关系唯一性也不保证。试着做些测试,我不完全正确。当我们创建关系时,MERGE
将在两个节点上获取锁,但因为我们在匹配时不锁定节点,所以在并发执行查询时可能会创建重复关系。在我的情况下,remove-non-existence属性不起作用。但设置和删除节点上的属性会起作用<代码>匹配(a),(b)设置a