超时到期后,事务未过期

时间:2018-01-09 16:23:47

标签: neo4j

我们正在使用neo4j(3.1.5-enterprise)来提供我们的服务。 (通过HTTP)

我们在neo4j配置文件中设置了dbms.transaction.timeout=150s

我们的场景可能需要150秒以上的时间,但我们希望交易在150秒后过期。

由于某种原因,它没有发生,并且交易一直持续到完全执行但是150秒后它没有被停止,为什么要猜?

在我们的应用程序日志中,我可以看到以下异常(下面有更多堆栈跟踪详细信息):

neo.db.NeoHttpDriver - Errors in response:
  [NeoResponseError{
     code='Neo.DatabaseError.Statement.ExecutionFailed', 
     message='Transaction timeout. (Overtime: 23793 ms).', 
     stackTrace='org.neo4j.kernel.guard.GuardTimeoutException: Transaction timeout. (Overtime: 23793 ms).
     ...

此外,我们的服务步骤(在可能需要很长时间的特定方案中)通常是打开一个事务,锁定一些公共实体并继续。由于事务未在150秒后过期并释放(因此公共实体继续被锁定),因此其他线程也可能被锁定很长时间。

谢谢! 奥勒尔

异常堆栈跟踪:

15:00:59.627 [DefaultThreadPool-7] DEBUG c.e.e.m.neo.db.NeoHttpDriver - Errors in response: [NeoResponseError{code='Neo.DatabaseError.Statement.ExecutionFailed', message='Transaction timeout. (Overtime: 23793 ms).', stackTrace='org.neo4j.kernel.guard.GuardTimeoutException: Transaction timeout. (Overtime: 23793 ms).
            at org.neo4j.kernel.guard.TimeoutGuard.check(TimeoutGuard.java:71)
            at org.neo4j.kernel.guard.TimeoutGuard.check(TimeoutGuard.java:57)
            at org.neo4j.kernel.guard.TimeoutGuard.check(TimeoutGuard.java:49)
            at org.neo4j.kernel.impl.api.GuardingStatementOperations.nodeCursorById(GuardingStatementOperations.java:300)
            at org.neo4j.kernel.impl.api.OperationsFacade.nodeHasProperty(OperationsFacade.java:343)
            at org.neo4j.cypher.internal.spi.v3_1.TransactionBoundQueryContext$NodeOperations.hasProperty(TransactionBoundQueryContext.scala:319)
            at org.neo4j.cypher.internal.compatibility.ExceptionTranslatingQueryContextFor3_1$ExceptionTranslatingOperations$$anonfun$hasProperty$1.apply$mcZ$sp(ExceptionTranslatingQueryContextFor3_1.scala:245)
            at org.neo4j.cypher.internal.compatibility.ExceptionTranslatingQueryContextFor3_1$ExceptionTranslatingOperations$$anonfun$hasProperty$1.apply(ExceptionTranslatingQueryContextFor3_1.scala:245)
            at org.neo4j.cypher.internal.compatibility.ExceptionTranslatingQueryContextFor3_1$ExceptionTranslatingOperations$$anonfun$hasProperty$1.apply(ExceptionTranslatingQueryContextFor3_1.scala:245)
            at org.neo4j.cypher.internal.spi.v3_1.ExceptionTranslationSupport$class.translateException(ExceptionTranslationSupport.scala:32)
            at org.neo4j.cypher.internal.compatibility.ExceptionTranslatingQueryContextFor3_1.translateException(ExceptionTranslatingQueryContextFor3_1.scala:34)
            at org.neo4j.cypher.internal.compatibility.ExceptionTranslatingQueryContextFor3_1$ExceptionTranslatingOperations.hasProperty(ExceptionTranslatingQueryContextFor3_1.scala:245)
            at org.neo4j.cypher.internal.compiler.v3_1.spi.DelegatingOperations.hasProperty(DelegatingQueryContext.scala:221)
            at org.neo4j.cypher.internal.compiler.v3_1.pipes.AbstractSetPropertyOperation.setProperty(SetOperation.scala:98)
            at org.neo4j.cypher.internal.compiler.v3_1.pipes.SetEntityPropertyOperation.set(SetOperation.scala:117)
            at org.neo4j.cypher.internal.compiler.v3_1.pipes.SetPipe$$anonfun$internalCreateResults$1.apply(SetPipe.scala:31)
            at org.neo4j.cypher.internal.compiler.v3_1.pipes.SetPipe$$anonfun$internalCreateResults$1.apply(SetPipe.scala:30)
            at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
            at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
            at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator$$anonfun$next$1.apply(ResultIterator.scala:71)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator$$anonfun$next$1.apply(ResultIterator.scala:68)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator$$anonfun$failIfThrows$1.apply(ResultIterator.scala:94)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.decoratedCypherException(ResultIterator.scala:103)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.failIfThrows(ResultIterator.scala:92)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.next(ResultIterator.scala:68)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.next(ResultIterator.scala:49)
            at scala.collection.Iterator$class.foreach(Iterator.scala:893)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.foreach(ResultIterator.scala:49)
            at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:59)
            at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:183)
            at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:45)
            at scala.collection.TraversableOnce$class.to(TraversableOnce.scala:310)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.to(ResultIterator.scala:49)
            at scala.collection.TraversableOnce$class.toList(TraversableOnce.scala:294)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.toList(ResultIterator.scala:49)
            at org.neo4j.cypher.internal.compiler.v3_1.EagerResultIterator.<init>(ResultIterator.scala:35)
            at org.neo4j.cypher.internal.compiler.v3_1.ClosingIterator.toEager(ResultIterator.scala:53)
            at org.neo4j.cypher.internal.compiler.v3_1.executionplan.DefaultExecutionResultBuilderFactory$ExecutionWorkflowBuilder.buildResultIterator(DefaultExecutionResultBuilderFactory.scala:109)
            at org.neo4j.cypher.internal.compiler.v3_1.executionplan.DefaultExecutionResultBuilderFactory$ExecutionWorkflowBuilder.createResults(DefaultExecutionResultBuilderFactory.scala:99)
            at org.neo4j.cypher.internal.compiler.v3_1.executionplan.DefaultExecutionResultBuilderFactory$ExecutionWorkflowBuilder.build(DefaultExecutionResultBuilderFactory.scala:68)
            at org.neo4j.cypher.internal.compiler.v3_1.executionplan.InterpretedExecutionPlanBuilder$$anonfun$getExecutionPlanFunction$1.apply(ExecutionPlanBuilder.scala:164)
            at org.neo4j.cypher.internal.compiler.v3_1.executionplan.InterpretedExecutionPlanBuilder$$anonfun$getExecutionPlanFunction$1.apply(ExecutionPlanBuilder.scala:148)
            at org.neo4j.cypher.internal.compiler.v3_1.executionplan.InterpretedExecutionPlanBuilder$$anon$1.run(ExecutionPlanBuilder.scala:123)
            at org.neo4j.cypher.internal.compatibility.CompatibilityFor3_1$ExecutionPlanWrapper$$anonfun$run$1.apply(CompatibilityFor3_1.scala:275)
            at org.neo4j.cypher.internal.compatibility.CompatibilityFor3_1$ExecutionPlanWrapper$$anonfun$run$1.apply(CompatibilityFor3_1.scala:273)
            at org.neo4j.cypher.internal.compatibility.exceptionHandlerFor3_1$runSafely$.apply(CompatibilityFor3_1.scala:190)
            at org.neo4j.cypher.internal.compatibility.CompatibilityFor3_1$ExecutionPlanWrapper.run(CompatibilityFor3_1.scala:273)
            at org.neo4j.cypher.internal.PreparedPlanExecution.execute(PreparedPlanExecution.scala:26)
            at org.neo4j.cypher.internal.ExecutionEngine.execute(ExecutionEngine.scala:107)
            at org.neo4j.cypher.internal.javacompat.ExecutionEngine.executeQuery(ExecutionEngine.java:59)
            at org.neo4j.server.rest.transactional.TransactionHandle.safelyExecute(TransactionHandle.java:371)
            at org.neo4j.server.rest.transactional.TransactionHandle.executeStatements(TransactionHandle.java:323)
            at org.neo4j.server.rest.transactional.TransactionHandle.execute(TransactionHandle.java:230)
            at org.neo4j.server.rest.transactional.TransactionHandle.execute(TransactionHandle.java:119)
            at org.neo4j.server.rest.web.TransactionalService.lambda$executeStatements$0(TransactionalService.java:203)

2 个答案:

答案 0 :(得分:0)

问题很可能是tx正在等待锁定。在Neo4j 3.2之前,dbms.transaction.timeout不能涵盖终止等待锁定的事务的情况(或者更确切地说,它将标记为终止,但实际终止将不会发生,直到获得锁定。)< / p>

在Neo4j 3.2中,引入了dbms.lock.acquisition.timeout,它会中断等待锁并允许线程检查tx是否已经终止并采取适当的措施。

答案 1 :(得分:0)

以下内容基于Neo4j支持提供的答案:

  1. <强> dbms.lock.acquisition.timeout
    作为起点,dbms.lock.acquisition.timeout仅在Neo4j 3.2中添加,3.1不存在。我们还没有锁定获取超时,因此锁定的等待时间可以超过设定的限制。像GC这样的东西也可以延长时间。但是,正如您目前使用的是3.1.5,dbms.lock.acquisition.timeout尚未执行。

  2. <强> dbms.transaction.timeout
    dbms.transaction.timeout标记了一个终止事务,但是检查这个并执行终止的实际逻辑发生在正在运行的线程上,而不是等待锁定,并且不会导致线程被唤醒和检查。大概是在超时时终止线程的逻辑是某个其他线程定期检查事务的执行时间,如果超过事务超时,则在事务上设置boolean变量以指示它被标记为终止。线程的实际终止可能发生在事务的事件循环中,它检查该变量以查看它是否标记为终止,然后终止并回滚。当另一个线程已经持有锁时,尝试获取锁的线程进入等待状态。在此等待状态期间,事件循环未被处理,因此线程永远不会到达事件循环中的点,在那里它可以检查它是否已被标记为已终止并处理它。

  3. 底线:
    dbms.transaction.timeout不会导致硬超时,它只会将事务标记为超时,这会导致在检查到标志后回滚。