Neo4j:死锁内存泄漏

时间:2013-06-13 09:45:32

标签: java neo4j deadlock out-of-memory

我正在尝试插入大量的联系人和关系(数百万)。为了加快速度,我想我会将它们批处理,然后让多个线程同时插入它们。这会导致一些死锁,但由于我可以重试它们,所以我没有遇到任何问题。

   public void doBatch(final Collection<Object> rows) throws Exception {
    int retryCount = 3;
    while(!(retryCount<3)) {
        Transaction tx = graphdb.beginTx();
        try {
            for (Object row : rows) {
                String[] fields = ((String) row).split(DELIMITER, -1);
                if (fields.length < 4) {
                    log.error("Not enough fields to process row:" + row);
                } else {
                    addLineToGraph(fields[0], fields[1], fields[2], fields[3]);
                }
            }
            tx.success();
            retryCount = 0;
        } catch (DeadlockDetectedException dead) {
            tx.failure();
            retryCount--;
            log.warn("Retry deadlock");
        } catch (Exception e) {
            tx.failure();
            throw e;
        } finally {
            tx.finish();
        }
    }
}

不幸的是,经过几个小时的运行并且遇到很多死锁后,即使在尝试使用10G堆之后,我也会耗尽内存(超出GC开销限制)。在分析堆栈转储后,我注意到了很多很多的锁:

One instance of "org.neo4j.kernel.impl.transaction.RWLock" loaded by "sun.misc.Launcher$AppClassLoader @ 0xc0271350" occupies 672.139.928 (84,78%) bytes.
The memory is accumulated in one instance of "java.util.HashMap$Entry[]" loaded by "<system class loader>".

我的印象是这是由于失败的事务没有释放锁所引起的,因此我将我的代码限制为单个线程,这将确保不再发生死锁。执行此操作后,我将看到由垃圾收集引起的正常锯齿图表,并且不再出现内存错误。 根据我的理解tx.finish();应该清理一切吗?或者我在这里遗漏了什么?

我在嵌入模式下使用neo4j 2.0.0-M03。

2 个答案:

答案 0 :(得分:0)

如果要更新关系节点的任何属性,然后释放锁

,请使用锁

答案 1 :(得分:0)

我升级到2.0.0-M05,现在我得到了不同的行为。我在PersistenceWindowPool类上获得了一个nullpointer。至少目前这个类不是完全线程安全的。他们告诉我它将在2.0中得到解决,但在此之前,我正在使用我自己的同类版本。

https://github.com/bennies/neo4j/commit/d8a0f4732f347f2038ebace83c14d37d4b1f8691

感谢所有关于替代解决方案的想法:)