如何诊断锁定问题
从 Neo4j 3.4 开始,可以更好地理解由并发查询引起的锁定问题。本文档不会详细介绍 Neo4j 中锁定的基础知识。我们假设一种情况,您并发运行大量查询 - 可能是相同的参数化查询或不同的查询。这些查询的典型执行时间远高于预期 - 您基本上认为 Neo4j “很慢”。事实上,这种观察结果的来源可能是您的查询试图获取公共节点上的锁,因此它们需要等待锁持有者释放锁。等待公共锁的查询实际上被串行化了。
在早期版本的 Neo4j 中,查询日志记录功能 允许添加与查询处于等待状态多长时间相关的信息,无论是在等待锁还是在等待 IO。这可以通过 neo4j.conf 参数 dbms.logs.query.time_logging_enabled=true
打开。但是,这仅向我们提供有关总等待时间的信息,而没有深入了解可能导致等待的节点或关系。
从 Neo4j 3.4 开始,以及新的存储过程 dbms.listTransactions()
,可以更好地理解延迟的原因。为了演示使用 2 个 cypher-shell 连接的过程,请运行以下 Cypher 代码
session1: merge (n:Lock {id:1}) set n.age=20 with n call apoc.util.sleep(200000) return n; session2: Match (n:Lock {id:1}) set n.age=85 return n;
第一个会话将把 id=1 的 :Lock 标签节点的 age
属性设置为 20,然后休眠 200 秒(从而保持对该节点的锁定)。第二个会话将尝试更新相同的节点并将其 age
属性设置为 85,但将在这些 200 秒内被阻塞。
在这 200 秒内,通过 Neo4j 浏览器运行 call dbms.listTransactions() yield transactionId, startTime, currentQueryId, currentQuery, status
将返回类似于以下内容的输出
从中我们可以看到,事务 1381/查询 1378 报告其状态为“被以下事务阻塞:[事务 1380]”,并且事务 1380 也列在输出中,并且两个事务都描述了当前查询。
此外,运行 call dbms.listActiveLocks('<currentQueryId>');
,例如 call dbms.listActiveLocks('query-1377');
将返回类似于以下内容的输出
从上面的输出中,我们看到查询 1377 对 id(n)=8432 的节点拥有排他节点锁。
通过这两个过程,您掌握了强大的工具,可以了解哪些节点/关系可能是锁争用的来源。
此页面是否有帮助?