Search code examples
orientdb

How to use sequence in multi-threaded enviroment


I try to create multiple vertexes in parallel:

public static void main(String[] args) throws InterruptedException {

    //create db and seq
    ODatabaseDocumentTx db = new ODatabaseDocumentTx("memory:/TestDB");
    db.create();
    OSequenceLibrary seqLib = db.getMetadata().getSequenceLibrary();
    seqLib.createSequence("testSeq",
      OSequence.SEQUENCE_TYPE.ORDERED,
      new OSequence.CreateParams().setStart(0L).setIncrement(1)
    );

    OrientGraphFactory factory = new OrientGraphFactory("memory:/TestDB", "admin", "admin").setupPool(1, 8);

    //mt
    Executor executor = Executors.newFixedThreadPool(8);

    CountDownLatch latch = new CountDownLatch(1000);
    for (int i = 1; i <= 1000; i++) {
        executor.execute(() -> {
            OrientGraph g = factory.getTx();
            try {
                OSequence seq = g.getRawGraph().getMetadata().getSequenceLibrary().getSequence("testSeq");
                OrientVertex v = g.addVertex("TestClass");
                v.setProperty("seq", seq.next());
                latch.countDown();
            } finally {
                g.shutdown();
            }
        });
    }
    latch.await(5, TimeUnit.SECONDS);
    System.exit(0);
}

And receive lots of exceptions:

com.orientechnologies.orient.core.exception.OConcurrentModificationException: Cannot UPDATE the record #7:0 because the version is not the latest. Probably you are updating an old record or it has been modified by another user (db=v2 your=v1)

How to use sequence in mt environment properly?


Solution

  • OrientDB is entirely based on an optimistic approach with no or few locks. For this reason you should catch the exception and retry. Example:

    OrientGraph g = factory.getTx();
    try {
      for( int retry = 0; retry < 100; ++retry ){
        try {
          OSequence seq = g.getRawGraph().getMetadata().getSequenceLibrary().getSequence("testSeq");
          OrientVertex v = g.addVertex("TestClass");
          v.setProperty("seq", seq.next());
          latch.countDown();
          break;
    
        } catch( ONeedRetryException e ) {
        }
      }
    } finally {
      g.shutdown();
    }