[ZODB-Dev] ZODB4 project plan

Shane Hathaway shane@zope.com
Tue, 14 Jan 2003 21:11:08 -0500 (EST)


On Tue, 14 Jan 2003, Christian Reis wrote:
> Shane, we've been integrating these changes into our product this week
> and (I repeat!) it's been working really cool. Needless to say, the ZODB
> rocks; I would never have imagined it would have been simple to change
> its transaction semantics. 
> 
> I've found this change is also a great way of explaining to people
> (without resorting to complications wrt threading) how the ZODB conflict
> management works, and I'm attaching a small testcase for others to look
> at and understand how ConflictErrors actually occur.

Cool.  If Jeremy approves, I can integrate it into the HEAD, which I
assume will be the basis for ZODB3-3_2-branch.

> One thing in the script I *don't* understand, however, is a
> ReadConflictError I get. The situation is best exemplified in the
> testcase, but it seems to be an issue with how BTrees work. I add an
> item to the root on connection 1, and commit() the change. If I try to
> access this item on the root for connection 2 (root2['item']) it raises
> the exception. Is this expected?

Yes.  Connection 2 is complaining that it loaded data that it shouldn't
see yet, since the data in connection 2 is based on an earlier
transaction.  You wouldn't want to mix data from multiple transactions,
after all.  ZODB isn't quite smart enough to actually try to load the data
from the earlier transaction, so it instead raises a read conflict error.  
(As I understand it, the multi-version concurrency control project is
meant to fix this.)

In Zope, conflict errors (including read conflicts) are quite rare because 
connections are short lived.  As ZODB usage grows beyond Zope, better 
support for long-lived transactions will likely become more important.

> I suppose it is a way of catching conflicts early on -- since we already
> have a key called `item' on connection1's object, it wouldn't make sense
> to allow us to create one on connection2 and then have commit() bail out
> on us. Am I right?
> 
> However, the funny part is that if I *access* the object in connection2
> prior to committing it in connection1, all is well and safe. Is this
> because the transaction machinery understands that we know about the
> item in both connections before the first transaction goes in?

In that case, the object is already in the cache, so no call to 
Connection.setstate() happens.  Connection.setstate() is the only piece of 
code that raises ReadConflictError.  Now, I'm not 100% certain that's what 
*should* happen, but it's reasonable.

Shane