java - 在同一事务中锁定的节点之间创建关系的 Neo4j 死锁

标签 java transactions neo4j deadlock

我的 Neo4j 服务器在执行并发请求时抛出 DeadlockDetectedExceptions,我不明白为什么。

以下代码由客户端 REST 请求调用的服务器插件调用,并发生在单个事务中。

  Node nFollowing = loadUser(idFollowing);
  Node nFollowed = loadUser(idFollowed);

  // locking order to avoid deadlocks
  if (Long.valueOf(idFollowing) < Long.valueOf(idFollowed)) {
    tx.acquireWriteLock(nFollowing);
    tx.acquireWriteLock(nFollowed);
  } else {
    tx.acquireWriteLock(nFollowed);
    tx.acquireWriteLock(nFollowing);
  }

  // create relationship if not present
  for (Relationship followship : nFollowing.getRelationships(
    EdgeType.FOLLOWS, Direction.OUTGOING)) {
    if (followship.getEndNode().equals(nFollowed)) {
      return;
    }
  }
  nFollowing.createRelationshipTo(nFollowed, EdgeType.FOLLOWS);

虽然我想到了死锁,但抛出以下异常,表明在创建关系时发生了死锁。

异常(略有减少):

"ForsetiClient[78] can't acquire ExclusiveLock{owner=ForsetiClient[73]} on  
  RELATIONSHIP(49), because holders of that lock are waiting for ForsetiClient[78].\n
  Wait list:ExclusiveLock[ForsetiClient[73] waits for [73, 78, ]]",
"exception" : "DeadlockDetectedException",
"fullname" : "org.neo4j.kernel.DeadlockDetectedException",
"stacktrace" : [
  "org.neo4j.kernel.ha.lock.forseti.ForsetiClient.markAsWaitingFor(ForsetiClient.java:611)",
  "org.neo4j.kernel.ha.lock.forseti.ForsetiClient.acquireExclusive(ForsetiClient.java:190)",
  "org.neo4j.kernel.impl.nioneo.xa.TransactionalRelationshipLocker.getWriteLock(TransactionalRelationshipLocker.java:33)",
  "org.neo4j.kernel.impl.core.NodeProxy.createRelationshipTo(NodeProxy.java:455)",
  "de.uniko.sebschlicht.neo4j.graphity.WriteOptimizedGraphity.addFollowship(WriteOptimizedGraphity.java:40)",
  "de.uniko.sebschlicht.neo4j.graphity.Graphity.addFollowship(Graphity.java:115)",
  "de.uniko.sebschlicht.neo4j.GraphityBaselinePlugin.follow(GraphityBaselinePlugin.java:38)",
  "org.neo4j.server.rest.web.ExtensionService.invokeGraphDatabaseExtension(ExtensionService.java:134)",
  "org.neo4j.server.rest.transactional.TransactionalRequestDispatcher.dispatch(TransactionalRequestDispatcher.java:139)"
]

我不明白为什么:我已经为 nFolloingnFollowed 锁定了。事实上,死锁的目标不是节点锁,而是关系锁。由于关系仅在关系不存在时才创建,因此锁持有者必须是当前关系。

如果这是正确的锁持有人正在等待自己。 我怎样才能避免这种情况或者还有什么异常想说的?

以防万一: 我不想使用 synchronized block ,即 suggested还有marked as to be avoided通过 Neo4j,因为它会大大降低我的服务速度,而且我不希望这些并发请求经常发生。

最佳答案

死锁是由 snychronized block 和手动事务锁引起的。我错过了从我之前执行的测试中删除 synchronized 语句。 虽然 synchronized 语句没有针对锁定的节点,但引发了异常。这两种锁定机制似乎是不兼容的。

这导致了对我不是很有帮助的奇怪错误消息。

关于java - 在同一事务中锁定的节点之间创建关系的 Neo4j 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25161837/

相关文章:

java - 按两个属性对对象进行排序

java - 在 Java 中使用 STR_TO_DATE 插入日期,使用 PreparedStatement

neo4j - 在图形数据库中保留节点和关系历史

Neo4j 家谱关系设计

java - Android:Java:使用 key 而不是密码解密 AES

java - 在Android中不断重新生成不同的随机数

C# - 业务层事务的使用(SQLServer 2005+,Oracle) - 很好的例子

postgresql - sequelize 更新事务锁行

java - 标准 XAConnectionHandle :prepareStatement should not be used outside an EJBServer

java - 使用 cypher 获取带有标签和索引的节点