[Zope-dev] Bug in all database adapters?

Matthew T. Kromer matt@zope.com
Wed, 08 Aug 2001 15:35:58 -0400


Actually, it's probably worse than that --

Multiple transactions can be in flight at any given time;
without explicitly coding a transaction ID into databases like
Oracle, everything falls under "default transaction" which
essentially means anything on a connection gets a new
transaction ID every commit or rollback.  However, a connection
object could theoretically be shared between threads (Zope tries
to avoid this by creating new instances of objects for each
thread, but you can work around that if you try hard enough). 
Thus, since commit/rollback happens on the CONNECTION and not
the STATEMENT (cursor), if two separate threads use the same
connection object and one aborts, the other will have its data
rolled back at the database level but not at Zope.  This is NOT
the common case -- you'd have to really try hard to share
objects between threads, because ZODB will make a NEW object per
thread (so you would have to have a product that participated in
the sharing) -- but it's still possible, IMHO.

However, I'm not sure if the solution is as simple as fixing TM
to provide a tm_abort or not.  I dont have any good test cases
to reproduce the behavior, so I end up doing a lot of guessing
as to what the proper solution should be without being able to
prove it.

Shai Berger wrote:
> 
> Hi,
> 
> I think I just found a deep bug that runs through
> most, if not all, relational database adapters, and
> some other products (notably, session management) too.
> 
> These products usually inherit ZRDB.TM, and trust
> it for their trnasaction management. The adapters
> usually just implement _begin (if they need to start
> the transaction explicitly), _abort and _finish.
> 
> The problem is that TM handles two-phase-commit quite
> badly, or so it seems to me. Since most DAs don't need
> to prepare for commits, it ignores tpc_begin (the first
> phase), and calls _finish on tpc_finish (the second phase).
> 
> Now, since it ignores tpc_begin, TM's authors thought
> they can ignore tpc_abort too -- and they did. However,
> this is wrong. If an object raises an exception in the
> first phase, the only method called for other ones
> may be tpc_abort. As a result, database transactions
> will be left hanging -- when the Zope transaction ends,
> they will be neither committed nor rolled back, and
> any locks they acquired will stay in force.
> 
> I have seen this in Zope 2.3.2, but as far as I've seen
> the changelogs show nothing related in later versions.
> 
> Am I missing something?