我在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;
> '
BOOM。 Neo4j卡住了!为了清楚起见,我知道MATCH语句并没有永远在这里,因为这次我只在我的数据库中输入了大约200万个节点,并且单独调用match语句运行得非常好。我甚至为这个唯一属性设置了索引(参见上面的模式调用)。
那么这里发生了什么?我认为如果我只插入一个节点,那么树的初始创建不应该是一个太大的问题。我的第一次尝试似乎完美无瑕。我不确定这次我做了多少不同的事情,除了用我拥有的5800万条记录中的200万填充我的数据库。 (所以它应该更快)。
我实际上让这个命令运行了几个小时,它也只在我的系统上运行了几分钟。我对这里发生的事情感到很困惑。有没有人有任何想法?无论如何我能看到neo4j正在积极地做这个命令吗? (请记住我正在使用社区版)
我正在运行neo4j的3.0.3版本,3.0.3.39 timetree / graphaware和CentOS 7服务器。
我唯一的想法是,我一直在调用cypher语句并在它们提交之前取消它们,无论是通过python还是cmd行shell工具。是否有可能通过在大交易结束前取消大交易而过多地搞乱交易经理?
例如:
/neo4j-shell -c 'MATCH (r:record) CALL ga.timetree.events.attach(....) ....'
然后在control-C
运行约2小时后点击dbms.memory.heap.max_size=16000
而没有完成。
更新:
好的,所以我调查了我的日志文件并发现了一些问题。由于没有足够的内存,我的线程似乎被阻止了。我想我的最大堆大小是人为限制的,而不是使用我机器上的可用资源。 (也许??)。所以我手动设置neo4j-shell
。
问题似乎现在消失了!我想我很困惑,因为我希望Java OOM出现在{{1}}工具的响应中而不是空转,就像取得进展一样。
答案 0 :(得分:1)
$ ./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;
> '
此查询预计会将多少个节点附加到时间树?
此程序不使用批处理,因此它仅限于您的记忆在单个事务中可以执行的操作(现在在我们的待办事项中)。
也就是说,手动将事件附加到树上通常没有意义,这个过程是为了方便,但我们建议使用自动事件附件:
https://github.com/graphaware/neo4j-timetree#automatic-event-attachment
通过这种方式,重新附加完整数据库(或仅配置为附件的节点)将重新启动数据库,此过程将与批处理事务一起运行,这将显着加快所需的时间。