[Zope] Status of Zope Database Adapters (DAs)
Jim Fulton
jim@digicool.com
Thu, 15 Jul 1999 10:23:13 -0400
Christopher Petrilli wrote:
>
> OK gang, I've been beating my head against all the DAs of late, looking for
> thread safety issues (the long and the short is nothing is currently fully
> thread safe), however, as you read the attached document, you'll understand
> that getting them to work in a functional fashion is not going to be hard.
> We will be releasing fixed versions of Oracle, ODBC and perhaps one other in
> the very near future (this is my next task).
>
> If you see any glaring errors, please let me know, or if you know of tricks
> related to making something work in a thread-safe fashion, please let me
> know.
I'd like to make some addition to Chris' DA status document.
(I'll try to get this document, with my additions,
into the doc directory of the Zope distribution.)
- The global interpreter lock
Any database extension should release the Python global interpreter
lock when making database calls. Database calls can take a long time
and it makes no sense to block other threads while this is happening.
This is important for Zope 2 even when running with one application thread
(e.g. "python z2.py -t1"). ZServer uses a minimum of two threads, one for
medusa and n for application threads. A database extension that keeps the
global interpreter lock blocks medusa.
A database adapter has a C extension that does not contain the string
"Py_BEGIN_ALLOW_THREADS" is almost certainly broken *even* for
"single-threaded" Zope applications.
- Transactions
For databases that support transactions, ZODB wants to synchronize
transactions across ZODB and all of the external databases. This is
a *very* Good Thing.
Consider the following example. A request modifies some Zope
objects *and* modifies data in an Oracle table and in an Access table.
After modifying these data, an error occurs. At this point, you want to
undo all of the changes that were made. Without transactions, this
would be very difficult. The changes might have been made in very different
parts of the application and it would be necessary for the application to
keep track of old values so that they could be restored. Fortunately,
ZODB and transactions make error recovery simple. The application merely
has to:
get_transaction().abort()
when an error occurs. (This happens automatically if the request was
issued through ZPublisher.) The ZODB transaction manager will undo changes
made to Zope objects *and* will issue aborts to Oracle and Access to undo
changes made in those databases.
If you don't think that this is *very cool*, re-read the last paragraph and think
about it.
Now, supporting transactions does require some some special effort on the part of
the DA writer, and it will require even more effort for database adapters that
are not thread safe. Unfortunately, we (I) haven't does a good job of communicating
on this issue (or on DA writing in general).
For a DA to participate in ZODB transaction processing, it must:
- register with the transaction manager, and
- implement the prootcol that the transaction manager uses to
communicate with transaction-aware objects.
As a bonus, the protocols have changes in ZODB 3. (To implement
two-phase commit.)
In an effort to make implementing transaction support easier, I created
a mix-in class, TM, in Shared.DC.ZRDB.TM (lib/python/Shared/DC/ZRDB/TM.py).
This class does most of the work of implementing ZODB3 aware transaction support
for *both* ZODB 2 and ZODB 3. See the Gadfly DA for an example of how to use this.
All DAs for transaction-aware databases should either mix-in and use TM or
otherwise implement the ZODB 3 transaction protocol.
Now *here's the important part wrt threads*:
--------------------------------------------
If a database extension isn't thread safe, it isn't enough to protect extension *calls*
with a global lock. If a low-level database connection is shared among multiple threads,
it isn't enough to assure that only one thread uses the connection at once. You must assure
that only one thread is in a *transaction* at once. The connection must be locked at
transaction boundaries, not at call or even SQL boundaries.
We intend to provide some additional guidence and software for dealling with this issue in
the near future.
Jim
--
Jim Fulton mailto:jim@digicool.com Python Powered!
Technical Director (888) 344-4332 http://www.python.org
Digital Creations http://www.digicool.com http://www.zope.org
Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.