Neo4j / Cypher在高度并发的环境中创造了独特的关系

时间:2016-07-14 17:15:18

标签: neo4j cypher graph-databases nosql

我需要为给定的关系类型提供某种独特的约束。

(a)-[:RELATION]->(b)

为了达到这个目的,我正在使用CREATE UNIQUE (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_

使用额外的重试循环,指数退避过程可能出现死锁。

2 个答案:

答案 0 :(得分:3)

您需要在关系上使用MERGE,但事先需要获取锁以防止并发问题。这是移除非现有属性的副作用最容易实现的:

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)

答案 1 :(得分:0)

这就是我最后使用的方法

MATCH (a), (b) 
SET a._lock_ = true, b._lock_ = true 
MERGE (a)-[:RELATION]->(b) 
REMOVE a._lock_, b._lock_

使用指数退避的附加重试循环来处理可能的死锁。