You are not logged in Log in Join
You are here: Home » Members » mcdonc » HowTos » Use ZODB Transactions

Log in
Name

Password

 

Use ZODB Transactions

Using Zope's Transaction Manager

All work performed on data within the ZODB and other particpating transactional data stores is performed within the context of a transaction. Physically, the transaction manager is part of the Zope Object Database (the ZODB), but it will happily operate on participating non-ZODB data storage implementations as well. For instance, ZSQL methods make use of the Zope transaction machinery to peer ZODB transactions with relational database transactions. Therefore, it can be said that Zope's transaction manager can operate on one or multiple independent data stores. A transaction object is obtained from the transaction manager through a global accessor function get_transaction(). Performing operations on this object effects all registered data stores. Therefore, a commit against an obtained transaction object effects not only the ZODB, but all data stores who have registered an interest in the transaction machinery.

How Transactions Are Used By Zope

In the context of normal operation, the Zope publisher defines a transaction as the length of a single web request. The publisher makes use of the ZODB's transaction manager to commit or abort the transaction. If the request is successful, the transaction manager is called with a "commit", and all participating databases are committed. If the request is not successful (e.g. if an exception is raised during the request), the transaction manager is called with an "abort", and all participating databases are rolled back to a previous state.

Unless explicitly requested by a Zope application, subtransactions are not used within the context of a web request.

Manually Operating The Transaction Machinery

Application developers may operate the transaction machinery manually in order to support nonstandard transaction policies or subtransactions.

Manually operating the transaction machinery includes three steps:

  • Obtaining a transaction object.
  • Beginning a transaction.
  • Committing, aborting, or taking other actions upon the transaction object.

Obtaining a Transaction Object

Application developers may obtain a transaction object from with Zope Python code by calling the (builtin) method get_transaction() (this function is inserted into the Python builtins namespace when the ZODB package is imported). Here's an example:

  t = get_transaction()

Beginning a Transaction

A transaction is begun implicitly when working with ZODB objects. There is no need to explictly begin a transaction, though it is possible by calling the begin() method of a transaction object. Explicitly beginning a new transaction implicitly aborts any work done in the current transaction. Here's how to begin a transaction:

  get_transaction().begin()

Committing, Aborting, or Taking Other Actions Upon A Transaction Object

Once a transaction object is obtained, it may be operated upon. Transaction objects support three interface methods: commit(), abort(), and note().

commit()
commits the transaction.
abort()
aborts the transaction.
note()
adds a note to the transaction log regarding the current transaction.

Here's an example of committing a transaction (with preceding work shown for context):

  ob = self.getOb()
  ob.attr = 'foo'
  get_transaction().commit()

Here's an example of aborting the same set of work in this transaction:

  ob = self.getOb()
  ob.attr = 'foo'
  get_transaction().abort()

Here's an example of attaching a note to a transaction:

  ob = self.getOb()
  ob.attr = 'foo'
  get_transaction().note('assign of foo to ob.attr was in this transaction')

Subtransactions

During the course of a single transaction, portions of the work performed within the transaction can be committed or rolled back without committing or aborting the containing transaction. This is known as a subtransaction.

A subtransaction is caused by obtaining a transaction object and calling its commit() or abort() methods with a single true value.

An example of a subtransaction commit:

  get_transaction().commit(1)

A subtransaction commit saves all the work in the containing transaction done up to the point at which the subtransaction is committed.

An example of a subtransaction abort:

  get_transaction().abort(1) 

A subtransaction abort aborts all the work uncommitted since the beginning of the transaction or since the last subtransaction commit.

Data stores must explicitly support subtransactions. The ZODB supports subtransactions, however most relational databases do not. The operation performed in the context of subtransaction is undefined for these types of databases.

Why Subtransactions?

Normally, a Zope transaction keeps a list of objects modified within the transaction in a structure in RAM. This list of objects can grow quite large when there is a lot of work done across a lot of objects in the context of a transaction. Subtransactions write portions of this object list out to disk, freeing the RAM required by the transaction list. Using subtransactions can allow you to build transactions involving objects whose combined size is larger than available RAM.

See Also

Introduction To The Zope Object Database:

  http://www.zope.org/Members/jim/Info/IPC8/ZODB3/index.html

The ZODB How-To:

http://www.zope.org/Members/michel/HowTos/ZODB-How-To

The ZODB UML Model:

http://www.zope.org/Documentation/Developer/Models/ZODB