Today I had to figure out why something that should not create a write
transaction did create one.

The first step is easy, you pack the database, do the thing that should not
modify anything and look in the "undo" tab of your Zope site. There you'll
see if something was written or not, it comes up as an undoable transaction.

Then it is a matter of figuring out what happens. In this case, it was quite
a complex script with many parts. I wanted to see if I could narrow down the
problem by seeing what was actually changed. So, from my lib/python
directory, I ran this script:

from ZODB.FileStorage import FileStorage
storage = FileStorage('/path/to/var/Data.fs', read_only=1)
iter = storage.iterator()
while True:
transaction =
for rec in transaction:
print repr(rec.oid)

This prints out the "oids" of all modified objects in the transaction.

Then I can run zope in debug mode:

bin/zopectl debug

When I get the python
prompt, I can get the objects that were modified:

app._p_jar['the oid pasted from the previous script']

This allowed me to narrow down the search for the culprit quite a lot.
It still remains to figure out where in the code the modification is, but at least with the above you can get a rough idea of what is happening.
See also Debugging ZODB bloat which documents roughly this process.

(Post originally written by Lennart Regebro on the old Nuxeo blogs.)