{"id":3334,"date":"2019-06-14T13:35:48","date_gmt":"2019-06-14T11:35:48","guid":{"rendered":"http:\/\/blog.gocept.com\/?p=3334"},"modified":"2019-06-14T13:35:48","modified_gmt":"2019-06-14T11:35:48","slug":"undo-transactions-by-truncating-zodb-data-fs","status":"publish","type":"post","link":"https:\/\/blog.gocept.com\/2019\/06\/14\/undo-transactions-by-truncating-zodb-data-fs\/","title":{"rendered":"Undo transactions by truncating ZODB Data.fs"},"content":{"rendered":"\n

Sometimes I break the Data.fs of my ZODB in a way that the Zope instance cannot start any more or I want to try again a migration. In such situations it is handy that writing to a Data.fs means extending the file at the end. So the unwanted transaction can be truncated. Normally I use the following steps to do so:<\/p>\n\n\n\n

1. Install ZODB<\/code> in a virtualenv<\/h3>\n\n\n\n

This is needed to get the script named fstail<\/code>. If you are already using Python 3, call:
python3.7 -m venv v_zodb<\/code><\/p>\n\n\n\n

If you are still on Python 2, call:
virtualenv-2.7 v_zodb<\/code><\/p>\n\n\n\n

Caution:<\/strong> The Python major version (2 or 3) must match the version you are using for the Zope instance.<\/p>\n\n\n\n

Install the script into the virtual environment using:
cd v_zodb<\/code>
bin\/pip install ZODB<\/code><\/p>\n\n\n\n

2. Stop Zope and ZEO<\/h3>\n\n\n\n

Stop both Zope and (if used) the ZEO server. This is necessary for your cut to get noticed by client and server.<\/p>\n\n\n\n

3. Find the position where to cut<\/h3>\n\n\n\n

Call fstail<\/code>. With -n<\/code> you are able to specify the number of transactions to be shown:
bin\/fstail -n 20 path\/to\/Data.fs<\/code><\/p>\n\n\n\n

fstail<\/code> returns something like the following. Newer transaction are at the top: (These lines here are only some extracted from a longer output.)<\/p>\n\n\n\n

2019-04-24 08:38:44.622984: hash=0b59c10e6eaa947b2ec0538e26d9b4f9128c03cb\nuser=' admin' description='\/storage\/58bdea07-666c-11e9-8a63-34363bceb816\/edit' length=19180 offset=12296784 (+97)\n2019-04-24 08:38:06.823673: hash=3a595fb50b913bad819f0d5bd8d152e06bc695d7\nuser=' admin' description='\/portal\/site\/add-page-form' length=132830 offset=12121677 (+58)\n2019-02-26 10:28:10.856626: hash=5b2b0fbc33b53875b7110f82b2fe1793245c590b\nuser=' admin' description='\/index_html\/pt_editAction' length=444 offset=11409587 (+54)<\/pre>\n\n\n\n

Using the provided information in user<\/code> and description<\/code> you should be able to find the transaction from which on newer transactions should be removed. You need the provided value after offset=<\/code> to do the cut.<\/p>\n\n\n\n

In my example above, if \/portal\/site\/add-page-form<\/code> is the faulty transaction, my cut point is 12121677<\/code>.<\/p>\n\n\n\n

4. 3, 2, 1 \u2026 cut<\/h3>\n\n\n\n

Caution:<\/strong> Every transaction after the cut point (including the one you took the offset<\/code> from) will get removed by cutting.<\/p>\n\n\n\n

Get a truncate tool of your choice. I am using here one of Folkert van Heusden<\/a> which comes with MacPorts and claims to be command-line compatible with the (Free-)BSD version.<\/p>\n\n\n\n

In my example I would call it using:
truncate -s 12121677 path\/to\/Data.fs<\/code><\/p>\n\n\n\n

That’s all. Start ZEO and Zope again to be back in transaction history where you have cut.<\/p>\n\n\n\n

References<\/h2>\n\n\n\n