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