OrientDB concurrent graph operations in Java -
i'm trying use orientdb (v2.1.2) in multithreaded environment (java 8) update vertex within multiple threads. i'm aware orientdb using mvcc , operations may fail , have executed again.
i wrote small unit test tries provoke such situations waiting on cyclic barrier within threads fork. unfortunately test fails obscure exception 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' subclass of 'e'' must executed outside active transaction: transaction committed , reopen right after it. avoid behavior execute outside transaction sep 21, 2015 3:00:24 pm com.orientechnologies.common.log.ologmanager log warning: {db=tinkerpop} requested command 'create edge type 'testedge_1442840424480' subclass of 'e'' must executed outside active transaction: transaction committed , reopen right after it. avoid behavior execute outside transaction exception in thread "thread-4" com.orientechnologies.orient.core.exception.oschemaexception: cluster id 11 belongs class testedge_1442840424480     @ com.orientechnologies.orient.core.metadata.schema.oschemashared.checkclustersareabsent(oschemashared.java:1264)     @ com.orientechnologies.orient.core.metadata.schema.oschemashared.docreateclass(oschemashared.java:983)     @ com.orientechnologies.orient.core.metadata.schema.oschemashared.createclass(oschemashared.java:415)     @ com.orientechnologies.orient.core.metadata.schema.oschemashared.createclass(oschemashared.java:400)     @ com.orientechnologies.orient.core.metadata.schema.oschemaproxy.createclass(oschemaproxy.java:100)     @ com.tinkerpop.blueprints.impls.orient.orientbasegraph$6.call(orientbasegraph.java:1387)     @ com.tinkerpop.blueprints.impls.orient.orientbasegraph$6.call(orientbasegraph.java:1384)     @ com.tinkerpop.blueprints.impls.orient.orientbasegraph.executeoutsidetx(orientbasegraph.java:1739)     @ com.tinkerpop.blueprints.impls.orient.orientbasegraph.createedgetype(orientbasegraph.java:1384)     @ com.tinkerpop.blueprints.impls.orient.orientbasegraph.createedgetype(orientbasegraph.java:1368)     @ com.tinkerpop.blueprints.impls.orient.orientbasegraph.createedgetype(orientbasegraph.java:1353)     @ com.tinkerpop.blueprints.impls.orient.orientvertex.addedge(orientvertex.java:928)     @ com.tinkerpop.blueprints.impls.orient.orientvertex.addedge(orientvertex.java:832)     @ com.gentics.test.orientdb.orientdbtinkerpopmultithreadingtest.lambda$0(orientdbtinkerpopmultithreadingtest.java:31)     @ com.gentics.test.orientdb.orientdbtinkerpopmultithreadingtest$$lambda$1/1446001495.run(unknown source)     @ java.lang.thread.run(thread.java:745)   the test using simple in-memory database. don't why orientdb checking cluster actions:
cluster id 11 belongs class testedge
somehow issue appears when try create 2 edges 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 2 threads     (int = 0; < 2; i++) {         final int threadno = i;         threads.add(run(() -> {             system.out.println("running thread [" + threadno + "]");             // start new transaction , 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 spawned threads     (thread thread : threads) {         thread.join();     } }  protected thread run(runnable runnable) {     thread thread = new thread(runnable);     thread.start();     return thread; }   the complete sources testcase can found here:
in general thankful example demonstrates how deal mvcc conflicts when using orientdb in embedded multithreaded java environment.
update:
i noticed problem no longer occures when reload vertex within thread via tx.getvertex(vertex.getid()) (not via .reload()). various errors when pass vertex object reference thread , use there. assume orientvertex class not threadsafe.
- you right all graph elements not thread safe.
 - reason of exception following when create edge, underneath of graph database create document class equals label of edge. if class absent transaction committed automatically , new class inside of schema created. each class mapped cluster in database (it table) when add edges concurrently @ same time create same class , result same cluster created. 1 thread wins other fails exception cluster given name created. suggest create classes aka labels of edges if possible before add edges @ runtime.
 
one more suggestion. should think orientgraph instance if connection server. best usage following:
- setup pool in orientgraphfactory
 - acquire graph instance before transaction.
 - execute transaction.
 - call .shutdown(), not create long living graph instances.
 
Comments
Post a Comment