私は複数のスレッド内から頂点を更新するマルチスレッド環境(Java 8)でorientdb(v2.1.2)を使用しようとしています。私はorientdbがMVCCを使用していることを認識しているため、これらの操作は失敗し、再度実行する必要があります。OrientDBのJavaでの同時グラフ操作
私はスレッドiフォーク内の周期的な障壁を待ってこのような状況を引き起こそうとする小さなユニットテストを書いた。残念ながらテストは、私は理解していない無名の例外で失敗します。
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)
テストは、単純なインメモリ・データベースを使用しています。 orientdbは、一部のクラスタ・アクションをチェックして、なぜ私は得ることはありません:
Cluster with id 11 already belongs to class testedge
を私は同じラベルを持つ2つのエッジを作成しようとすると、どういうわけか、この問題がのみ表示されます。
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;
}
テストケースのための完全なソース
は、ここで見つけることができます:一般的に私はorientdb使用している場合MVCCの競合に対処する方法を示す例のために非常に感謝するでしょう埋め込みマルチスレッドJava環境
アップデート:私はtx.getVertex(vertex.getId())を介して、私のスレッド内で頂点をリロードするときに問題がもはやoccuresことに気づいていない
(ない.reload経由()) 。頂点オブジェクト参照をスレッドに渡してそこに使用すると、さまざまなエラーが発生します。私はOrientVertexクラスがスレッドセーフではないと仮定します。