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:

https://github.com/jotschi/orientdb-concurrency-test/blob/master/src/test/java/com/gentics/test/orientdb/orientdbtinkerpopmultithreadingtest.java#l18

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.

  1. you right all graph elements not thread safe.
  2. 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:

  1. setup pool in orientgraphfactory
  2. acquire graph instance before transaction.
  3. execute transaction.
  4. call .shutdown(), not create long living graph instances.

Comments

Popular posts from this blog

java - Date formats difference between yyyy-MM-dd'T'HH:mm:ss and yyyy-MM-dd'T'HH:mm:ssXXX -

c# - Get rid of xmlns attribute when adding node to existing xml -