I have the same question. Surely the underlying SDB code begins/commits a transaction when it does updates to the database. Does it do so on an individual update operation? In which case you would lose the atomicity of multiple updates done in a single transaction. If it does do little transactions with each update, this could be a cause of performance issues, which I am definitely seeing. This should be fully explained and documented.
-----Original Message----- From: Lebling, David (US SSA) [mailto:[email protected]] Sent: Monday, April 15, 2013 7:35 AM To: [email protected] Subject: RE: Concurrency in Jena/SDB Andy, I was hoping you might have some guidance as to what you mean by "You need to control the JDBC transaction in your code to get isolation between JVMs." Is there some interface in SDB that will accomplish this, or does this require SQL-implementation-specific code, thus tearing down the SDB façade? If it does require such implementation-specific code, do you have any pointers to examples which do it correctly? Is it necessary to write one's own transaction begin/commit/abort methods? Thanks, Dave -----Original Message----- From: Lebling, David (US SSA) [mailto:[email protected]] Sent: Thursday, April 11, 2013 9:15 AM To: [email protected] Subject: RE: Concurrency in Jena/SDB Andy, It has been used with Postgres and MySQL. Dave -----Original Message----- From: Andy Seaborne [mailto:[email protected]] Sent: Thursday, April 11, 2013 8:16 AM To: [email protected] Subject: Re: Concurrency in Jena/SDB David, Your not executing inside a database level (JDBC) transaction. I'm afraid model.begin/commit does not know about JDBC properly. You need to control the JDBC transaction in your code to get isolation between JVMs. Which SQL database are you using? Andy On 10/04/13 16:12, Lebling, David (US SSA) wrote: > The method below is a somewhat over-decorated (with extra non-production > checks and error log messages) version of "write a model to the SDB > repository safely" that I am using. The Individual res (or rather, the > in-memory model it is in) is written to the Model model (obtained via > SDBFactory.connectNamedModel), replacing any current contents. > > It attempts to protect the model update from horrible concurrency death > during the process. However, I'm seeing that in cases where there are > multiple readers and writers (in different services - i.e., different JVMs) > beating on the particular model, the error messages with "****" appear, > sometimes surprisingly often. When the first one appears, the second one also > always appears. > > The outcome in the above cases is a repository model that is empty when read > later. The obvious idea is that between model.removeAll() and the later > model.add() the reader is reading the temporarily empty model. I don't know > if that idea is correct, but I don't have any others. > > Any suggestions as to what I am doing wrong would be appreciated. > > /** > * Single place to write or delete a model from the store > * @param model store-based model > * @param res in-memory resource to write into model, or null to just > delete model */ void internalWrite(Model model, Individual res) { > if (model != null) { > try { > logger.debug("begin write model"); > model.enterCriticalSection(Lock.WRITE); > model.notifyEvent(GraphEvents.startRead); // TEST I don't know if > this is worth doing > model.begin(); > model.removeAll(); // clear out the existing statements in the repo > model > if (res != null) { > Model base = res.getOntModel().getBaseModel(); > if (base.size() == 0) { > logger.error("internalWrite: base model empty"); > } > model.add(base); // add in-memory model to repository model > if (model.size() == 0) { > logger.error("internalWrite: model empty after add"); // **** > if this happens **** > } > } > else { > logger.debug("internalWrite: resource passed is null: delete"); > } > model.commit(); > if (model.size() == 0) { > logger.error("internalWrite: model empty after commit"); // **** > this also happens **** > } > } > catch (SDBException ex) { > model.abort(); > logger.error(ex); > } > finally { > model.notifyEvent(GraphEvents.finishRead); // TEST I don't know if > this is worth doing > model.leaveCriticalSection(); > logger.debug("end write model"); > } > } > } > > Thanks, > > Dave > > David Lebling > BAE Systems, Inc. >
