[英]OrientDB concurrent graph operations in Java
I'm trying to use orientdb (v2.1.2) in an multithreaded environment (Java 8) where i update a vertex from within multiple threads. 我试图在多线程环境(Java 8)中使用orientdb(v2.1.2),我在多个线程中更新顶点。 I'm aware that orientdb is using MVCC and thus those operations may fail and have to be executed again. 我知道orientdb正在使用MVCC,因此这些操作可能会失败并且必须再次执行。
I wrote a small unit test that tries to provoke such situations by waiting on a cyclic barrier within the threads i fork. 我写了一个小单元测试,试图通过等待我fork的线程中的循环障碍来激发这种情况。 Unfortunately the test fails with an obscure Exception which i don't understand: 不幸的是,测试失败了一个模糊的异常,我不明白:
Sep 21, 2015 3:00:24 PM com.orientechnologies.common.log.OLogManager log
INFO: OrientDB auto-config DISKCACHE=10,427MB (heap=3,566MB os=16,042MB disk=31,720MB)
Thread [0] running
Thread [1] running
Sep 21, 2015 3:00:24 PM com.orientechnologies.common.log.OLogManager log
WARNING: {db=tinkerpop} Requested command 'create edge type 'testedge_1442840424480' as subclass of 'E'' must be executed outside active transaction: the transaction will be committed and reopen right after it. To avoid this behavior execute it outside a transaction
Sep 21, 2015 3:00:24 PM com.orientechnologies.common.log.OLogManager log
WARNING: {db=tinkerpop} Requested command 'create edge type 'testedge_1442840424480' as subclass of 'E'' must be executed outside active transaction: the transaction will be committed and reopen right after it. To avoid this behavior execute it outside a transaction
Exception in thread "Thread-4" com.orientechnologies.orient.core.exception.OSchemaException: Cluster with id 11 already belongs to class testedge_1442840424480
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.checkClustersAreAbsent(OSchemaShared.java:1264)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.doCreateClass(OSchemaShared.java:983)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:415)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:400)
at com.orientechnologies.orient.core.metadata.schema.OSchemaProxy.createClass(OSchemaProxy.java:100)
at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph$6.call(OrientBaseGraph.java:1387)
at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph$6.call(OrientBaseGraph.java:1384)
at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.executeOutsideTx(OrientBaseGraph.java:1739)
at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.createEdgeType(OrientBaseGraph.java:1384)
at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.createEdgeType(OrientBaseGraph.java:1368)
at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.createEdgeType(OrientBaseGraph.java:1353)
at com.tinkerpop.blueprints.impls.orient.OrientVertex.addEdge(OrientVertex.java:928)
at com.tinkerpop.blueprints.impls.orient.OrientVertex.addEdge(OrientVertex.java:832)
at com.gentics.test.orientdb.OrientDBTinkerpopMultithreadingTest.lambda$0(OrientDBTinkerpopMultithreadingTest.java:31)
at com.gentics.test.orientdb.OrientDBTinkerpopMultithreadingTest$$Lambda$1/1446001495.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
The test is using a simple in-memory database. 该测试使用的是简单的内存数据库。 I don't get why orientdb is checking some cluster actions: 我不明白为什么orientdb正在检查一些集群操作:
Cluster with id 11 already belongs to class testedge
Somehow this issue only appears when i try to create two edges with the same label. 不知何故,只有当我尝试使用相同的标签创建两个边时才会出现此问题。
private OrientGraphFactory factory = new OrientGraphFactory("memory:tinkerpop").setupPool(5, 20);
@Test
public void testConcurrentGraphModifications() throws InterruptedException {
OrientGraph graph = factory.getTx();
Vertex v = graph.addVertex(null);
graph.commit();
CyclicBarrier barrier = new CyclicBarrier(2);
List<Thread> threads = new ArrayList<>();
// Spawn two threads
for (int i = 0; i < 2; i++) {
final int threadNo = i;
threads.add(run(() -> {
System.out.println("Running thread [" + threadNo + "]");
// Start a new transaction and modify vertex v
OrientGraph tx = factory.getTx();
Vertex v2 = tx.addVertex(null);
v.addEdge("testedge", v2);
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
tx.commit();
}));
}
// Wait for all spawned threads
for (Thread thread : threads) {
thread.join();
}
}
protected Thread run(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.start();
return thread;
}
In general i would be very thankful for a example that demonstrates how to deal with MVCC conflicts when using orientdb in an embedded multithreaded java environment. 总的来说,我非常感谢一个演示如何在嵌入式多线程Java环境中使用orientdb时处理MVCC冲突的示例。
Update: 更新:
I noticed that the problem no longer occures when i reload the vertex within my thread via tx.getVertex(vertex.getId()) (not via .reload()). 我注意到当我通过tx.getVertex(vertex.getId())(而不是通过.reload())重新加载我的线程中的顶点时,问题不再发生。 I get various errors when i just pass the vertex object reference to my thread and use it there. 当我将顶点对象引用传递给我的线程并在那里使用它时,我得到各种错误。 I assume the OrientVertex class is not threadsafe. 我假设OrientVertex类不是线程安全的。
One more suggestion. 还有一个建议。 You should think about OrientGraph instance as if it is connection to the server. 您应该将OrientGraph实例视为与服务器的连接。 The best usage is following: 最佳用法如下:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.