On Thu, Aug 22, 2013 at 03:40:41PM -0600, Sean Upton wrote:
> Caveat to this below.
> 
> On Mon, Jul 15, 2013 at 7:54 AM, Marius Gedminas <mar...@gedmin.as> wrote:
> 
> > On Mon, Jul 15, 2013 at 03:36:21PM +0200, Pedro Ferreira wrote:
> > > We need to move a considerable number of persistent objects (~40K) from
> > > one module to another, and we were wondering what is the best strategy
> > > to follow.
> > ...
> > > Has anyone ever done anything like this? Which approach have you
> > > followed? Any suggestions?
> >
> > 1. Make sure all the classes are still importable from the old location
> >    ('from newmodule import MyPersistentSomething # BBB')
> >
> > That is sufficient to make it work.  If you also want to eradicate all
> > references to the old module name from your ZODB (e.g. because you'd
> > like to remove the BBB import), then proceed to step 2:
> >
> > 2. Write a script that loads every instance of this class and does a
> >
> >    obj._p_activate()  # actually not sure this is required, but won't hurt
> >    obj._p_changed = True
> >
> > and then commit the transaction.  Do the commit multiple times, after
> > each batch of several hundred objects, to avoid excessive memory usage.
> > Also be sure to handle conflict errors and retry that batch if you're
> > running this script on the live system.  Finding all instances is left
> > as an exercise for the reader (sometimes findObjectsProviding() helps,
> > if you use nested containers everywhere; sometimes application-specific
> > logic works best; sometimes you end up having to use ZODB iterators to
> > loop through every single object in the DB -- I believe zodbupdate does
> > that.)
> >
> 
> This works only partially, AFAICT.  It will update the stored class name of
> a persistent object.  It will not seek out and change the class name of the
> object in a reference.  Your step 3 (removing the BBB code) can break
> things (broken objects) as a result of this.  Fixing persistent objects is
> half the battle if you get broken references to them.

Ouch, you're absolutely right.

> You can verify that this is incomplete by creating a PersistentMapping of
> some simple objects, perform the trick above, commit, then pack.  You will
> still have the old BBB classname stored in the database in the references,
> unless you do a _p_changed=1 on the mapping containing/referencing the
> items as well (then commit).
> 
> I am not sure how to walk/iterate all oids for all transactions to get all
> possible referencing objects (I assume this is storage-specific, maybe
> building a reference map like Lawrence Rowe has done [1]).  This might be
> necessary to update the referencing objects?

ZODB has an iterator API that allows you to access all the objects.

I think SchoolTool used to have an evolution script that did precisely
this (walk all the objects, set _p_changed to force a write) to solve
this problem.

And then there's https://pypi.python.org/pypi/zodbupdate which sounds
exactly like the tool you want for this.

> [1] http://plone.org/documentation/kb/debug-zodb-bloat/inspectZodbUtils.py

Marius Gedminas
-- 
Killing gnome-session is likely to free substantial amounts of memory, but the
user's gratitude may be surprisingly limited.
                -- Jonathan Corbet in a LWN article about the OOM killer

Attachment: signature.asc
Description: Digital signature

_______________________________________________
For more information about ZODB, see http://zodb.org/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
https://mail.zope.org/mailman/listinfo/zodb-dev

Reply via email to