Ich versuche Orientdb (v2.1.2) in einer Multithread-Umgebung (Java 8) zu verwenden, wo ich einen Scheitelpunkt innerhalb von mehreren Threads aktualisieren. Mir ist bewusst, dass orientdb MVCC verwendet und daher diese Operationen möglicherweise fehlschlagen und erneut ausgeführt werden müssen.OrientDB gleichzeitige Graph-Operationen in Java
Ich schrieb einen kleinen Komponententest, der versucht, solche Situationen zu provozieren, indem er auf eine zyklische Barriere in den Threads i fork wartet. Leider versagt der Test mit einer obskuren Ausnahme, die ich nicht verstehe:
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)
Der Test eine einfache In-Memory-Datenbank verwendet. Ich verstehe nicht, warum Orientdb einige Cluster Aktionen überprüft:
Cluster with id 11 already belongs to class testedge
Irgendwie dieses Problem erscheint nur, wenn ich versuche, zwei Kanten mit dem gleichen Etikett zu erstellen.
für ein Beispiel wäre ich sehr dankbarIm Allgemeinen, die wie mit MVCC Konflikten zu bewältigen zeigt, wenn sie in einem mit Orientdb:
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;
}
die kompletten Quellen für den Testfall kann hier gefunden werden eingebettete Multithread-Java-Umgebung.
Update:
bemerkte ich, dass das Problem nicht mehr occures, wenn ich den Scheitelpunkt in meinem Thread über tx.getVertex (vertex.getId()) (nicht über .reload()) nachladen . Ich erhalte verschiedene Fehler, wenn ich den Vertex-Objektverweis nur an meinen Thread übergebe und ihn dort verwende. Ich nehme an, die OrientVertex-Klasse ist nicht threadsicher.