Tôi đang cố gắng sử dụng orientdb (v2.1.2) trong môi trường đa luồng (Java 8), nơi tôi cập nhật một đỉnh từ trong nhiều luồng. Tôi biết rằng orientdb đang sử dụng MVCC và do đó các hoạt động đó có thể bị lỗi và phải được thực thi lại.OrientDB hoạt động biểu đồ đồng thời trong Java
Tôi đã viết một bài kiểm tra đơn vị nhỏ cố gắng kích động các tình huống như vậy bằng cách chờ đợi trên một hàng rào tuần hoàn trong chủ đề ngã ba. Rất tiếc, thử nghiệm không thành công với Ngoại lệ tối nghĩa mà tôi không hiểu:
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)
Thử nghiệm đang sử dụng cơ sở dữ liệu trong bộ nhớ đơn giản. Tôi không hiểu tại sao orientdb đang kiểm tra một số hành động cụm:
Cluster with id 11 already belongs to class testedge
Bằng cách nào đó vấn đề này chỉ xuất hiện khi tôi cố gắng để tạo ra hai cạnh có cùng nhãn.
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;
}
Các nguồn hoàn chỉnh cho các testcase có thể được tìm thấy ở đây:
Nói chung tôi sẽ rất biết ơn cho một ví dụ chứng minh làm thế nào để đối phó với các cuộc xung đột MVCC khi sử dụng orientdb trong một môi trường java đa luồng nhúng.
Cập nhật:
tôi nhận thấy rằng vấn đề không còn occures khi tôi tải lại đỉnh trong chủ đề của tôi qua tx.getVertex (vertex.getId()) (không thông qua .reload()) . Tôi nhận được các lỗi khác nhau khi tôi chỉ cần vượt qua các tham chiếu đối tượng đỉnh để thread của tôi và sử dụng nó ở đó. Tôi cho rằng lớp OrientVertex không phải là luồng an toàn.