我在 Neo4j 中遇到了一个奇怪的问题。我最近一直在使用 GraphAware TimeTree 并填充它直到昨天进展顺利。由于我犯了一个错误,我不得不重建树,所以我让一个脚本在一夜之间运行(nohup)。
今天回来发现我的脚本只跑了3分钟!
$ ps aux | grep timetreepop
root 21840 0.0 0.0 195952 2816 ? S Jul28 0:00 sudo nohup python timetreepop.py
root 21841 0.0 0.2 381416 75016 ? S Jul28 0:03 python timetreepop.py
我在工作时注意到了这种行为,但我认为在我不活动时将其放置一夜会有所帮助。如果可能发生争用,我还关闭了我的其他 java 服务器进程。在这一点上,我的服务器只会在后台运行一个 python 龙卷风服务器,它不是很庞大,并且不会获得太多流量(一天几次点击)。
总而言之,我的系统中有大量可用的 RAM,CPU 没有在其他地方使用,并且没有其他进程在我的机器上运行大量 IO。使用top
/atop
显示具有可用资源的健康系统。
这是我的脚本正在执行的高级操作:
neo = neopop.handler()
for i, meta_id in enumerate(meta_gen(ship='KAOU')):
neo.populate_timetree(record=meta_id)
我的处理程序在构造函数中创建驱动程序和会话__init__
:
self.driver = graphdb.driver(config.NEO4J_HTTP_LINK)
self.session = self.driver.session()
我的生成器提供meta_id
的值是图表中节点中的唯一属性值。
该populate_timetree()
函数创建以下语句:
MATCH (r:record {meta:"KAQP_20120101v20001_0001"}) WITH r
CALL ga.timetree.events.attach({node: r, time: r.time, relationshipType: "observedOn", resolution:"Minute"})
YIELD node RETURN node.meta;
一切都很好,我第一次去。在弄乱了我的时间值之后,我删除了数据库,重新启动,然后再试一次。只有这一次,当我调用关闭会话时,我的程序会冻结:
neo.session.close()
注意:我实际上在我的__del__
解构器中调用它,(我知道这可能被认为是不好的做法,但到目前为止它一直对我有用并且适合我的需要。)
我已经仔细检查了我所有的代码是否有恶意的 readline 语句/任何可能导致它暂停的东西。还重新编译了我的包,其中包含所有这些代码。我知道事实上它被困在这个session.close()
声明中。
所以我尝试使用 Neo4j-shell 工具来看看是否有什么不同。首先是快速响应检查:
$ neoc 'schema'
Indexes
ON :record(meta) ONLINE (for uniqueness constraint)
Constraints
ON (record:record) ASSERT record.meta IS UNIQUE
好的,一切都好。现在我尝试使用 timetree 调用单个值:
$ ./neo4j-shell -c '
> MATCH (r:record {meta:"KAOU_20110613v20001_0000"}) WITH r
> CALL ga.timetree.events.attach({node: r, time: r.time, relationshipType: "observedOn", resolution:"Minute"})
> YIELD node RETURN node.meta;
> '
繁荣。Neo4j 卡住了!需要明确的是,我知道 MATCH 语句不会永远在这里,因为我这次只在我的数据库中放入了大约 200 万个节点,并且单独调用 match 语句运行得非常好。我什至为这个独特的属性设置了一个索引(参见上面的模式调用)。
那么这里发生了什么?如果我只插入一个节点,我认为树的初始创建应该不是太大的问题。我的第一次尝试似乎完美无缺。我不确定这次我做了什么不同,除了用我拥有的 5800 万条记录中的 200 万条填充我的数据库。(所以它应该更快)。
实际上,我让这个命令运行了几个小时,而且它在我的系统上也只运行了几分钟。我对这里发生的事情感到非常困惑。有没有人有任何想法?无论如何我可以看到neo4j正在积极地处理这个命令吗?(请记住,我使用的是社区版)
我在 CentOS 7 服务器上运行 neo4j 的 3.0.3 版本和 3.0.3.39 timetree / graphaware。
我唯一的想法是,我一直在调用 cypher 语句并在它们提交这么多次之前取消它们,无论是通过 python 还是命令行 shell 工具。通过在完成之前取消大交易,我是否有可能过多地与交易管理器混淆?
例如:
/neo4j-shell -c 'MATCH (r:record) CALL ga.timetree.events.attach(....) ....'
然后control-C
在它运行了大约2个小时后没有完成。
更新:
好的,所以我调查了我的日志文件并发现了一些问题。由于内存不足,我的线程似乎被阻塞了。我猜我的最大堆大小受到人为限制,并且没有使用我机器上的可用资源。(也许??)。所以我手动设置dbms.memory.heap.max_size=16000
.
现在问题似乎消失了!我想我很困惑,因为我希望 Java OOM 出现在neo4j-shell
工具的响应中,而不是像取得进展一样空转。