{"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
ZODB<\/code> in a virtualenv<\/h3>\n\n\n\nThis 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\nIf you are still on Python 2, call:
virtualenv-2.7 v_zodb<\/code><\/p>\n\n\n\nCaution:<\/strong> The Python major version (2 or 3) must match the version you are using for the Zope instance.<\/p>\n\n\n\nInstall the script into the virtual environment using:
cd v_zodb<\/code>
bin\/pip install ZODB<\/code><\/p>\n\n\n\n2. 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\nfstail<\/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\n2019-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\nUsing 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\nIn my example above, if \/portal\/site\/add-page-form<\/code> is the faulty transaction, my cut point is 12121677<\/code>.<\/p>\n\n\n\n4. 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\nGet 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\nIn my example I would call it using:
truncate -s 12121677 path\/to\/Data.fs<\/code><\/p>\n\n\n\nThat’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- This blog post is based on a post of David Beitey, see Plone\/Zope: Truncating a Data.fs back to a certain\u00a0date\/time<\/a><\/li>
- See also Zope \u2013 undo transactions via debug console<\/a> for another way to truncate a ZODB via undo.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"
truncate can be used to permanently set back a ZODB Data.fs to a certain point in transaction history.<\/p>\n","protected":false},"author":15344399,"featured_media":3335,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_newsletter_tier_id":0,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[10221],"tags":[780,217249,832,780014,4448008,72208,594099838],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/06\/cord-4088055_1920.jpg?fit=1920%2C1280&ssl=1","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pFP3y-RM","jetpack-related-posts":[{"id":3229,"url":"https:\/\/blog.gocept.com\/2018\/06\/07\/migrate-a-zope-zodb-data-fs-to-python-3\/","url_meta":{"origin":3334,"position":0},"title":"Migrate a Zope ZODB Data.fs to Python 3","author":"Michael Howitz","date":"June 7, 2018","format":false,"excerpt":"TL;DR Use\u00a0zodbupdate. Problem A ZODB\u00a0Data.fs\u00a0which was created under Python 2 cannot be opened under Python 3. This is prevented by using a different magic code in the first bytes of the file. This is done on purpose because str\u00a0has a different meaning for the two Python versions: Under Python 2\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2018\/06\/spring-3383890_1280.jpg?fit=1200%2C797&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2018\/06\/spring-3383890_1280.jpg?fit=1200%2C797&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2018\/06\/spring-3383890_1280.jpg?fit=1200%2C797&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2018\/06\/spring-3383890_1280.jpg?fit=1200%2C797&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2018\/06\/spring-3383890_1280.jpg?fit=1200%2C797&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":2789,"url":"https:\/\/blog.gocept.com\/2017\/10\/25\/testing-zope-4beta2\/","url_meta":{"origin":3334,"position":1},"title":"Migrating from Zope 2.13 to 4.0b2","author":"Michael Howitz","date":"October 25, 2017","format":false,"excerpt":"Beta-Testing Zope 4 together with PerFact Innovation","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1540,"url":"https:\/\/blog.gocept.com\/2016\/09\/02\/zodb-py3migrate-1\/","url_meta":{"origin":3334,"position":2},"title":"zodb.py3migrate: Migrate an existing ZODB Data.fs to be used with Python 3","author":"Michael Howitz","date":"September 2, 2016","format":false,"excerpt":"At\u00a0Berlin Strategic sprint 2016\u00a0we\u00a0developed a tool to analyze a ZODB Filestorage to find\u00a0Python 2 string objects. If\u00a0they are in an encoding besides ASCII this is\u00a0preventing using this Filestorage with Python 3 because of decoding errors arising on loading the pickles. The tool is even able to convert those strings either\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3285,"url":"https:\/\/blog.gocept.com\/2019\/03\/07\/zope-spring-cleaning-sprint\/","url_meta":{"origin":3334,"position":3},"title":"Zope spring cleaning sprint","author":"Michael Howitz","date":"March 7, 2019","format":false,"excerpt":"The last year before the sunset of the Python 2 land has begun. Earl Zope feels relatively well prepared to live in the Python 3 wonderland. Some issue are still open which are required for the final permission to stay in Python 3 wonderland: test and improve ZODB migrationupdate the\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/03\/cleaning-washing-cleanup-the-ilo-48889.jpeg?fit=1200%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/03\/cleaning-washing-cleanup-the-ilo-48889.jpeg?fit=1200%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/03\/cleaning-washing-cleanup-the-ilo-48889.jpeg?fit=1200%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/03\/cleaning-washing-cleanup-the-ilo-48889.jpeg?fit=1200%2C800&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/03\/cleaning-washing-cleanup-the-ilo-48889.jpeg?fit=1200%2C800&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3350,"url":"https:\/\/blog.gocept.com\/2019\/11\/13\/union-cms-released-on-python-3\/","url_meta":{"origin":3334,"position":4},"title":"union.cms released on Python 3","author":"Michael Howitz","date":"November 13, 2019","format":false,"excerpt":"union.cms is a content management system which was once developed on Zope 2. It was one of the early adopters of the Five technology aka using Zope 3 components in Zope 2. Now it is one of the proud early adopters of Zope 4 on Python 3. It is used\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"Green tree python","src":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/11\/green-tree-python-1312700.jpg?fit=1200%2C863&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/11\/green-tree-python-1312700.jpg?fit=1200%2C863&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/11\/green-tree-python-1312700.jpg?fit=1200%2C863&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/11\/green-tree-python-1312700.jpg?fit=1200%2C863&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/11\/green-tree-python-1312700.jpg?fit=1200%2C863&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3312,"url":"https:\/\/blog.gocept.com\/2019\/05\/10\/celebration-zope-4-final-release\/","url_meta":{"origin":3334,"position":5},"title":"Celebration: Zope 4 final release","author":"Michael Howitz","date":"May 10, 2019","format":false,"excerpt":"TL;DR: Zope 4 beta phase ended, final version released! After hard, long years of preparation Earl Zope now finally made it to get a permanent license for the Python 3 wonderland: In September 2016 almost 20 people started with the reanimation of Zope at the Zope Resurrection sprint. This marked\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/05\/fireworks-945386_1920.jpg?fit=1200%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/05\/fireworks-945386_1920.jpg?fit=1200%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/05\/fireworks-945386_1920.jpg?fit=1200%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/05\/fireworks-945386_1920.jpg?fit=1200%2C800&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2019\/05\/fireworks-945386_1920.jpg?fit=1200%2C800&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts\/3334"}],"collection":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/users\/15344399"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/comments?post=3334"}],"version-history":[{"count":13,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts\/3334\/revisions"}],"predecessor-version":[{"id":3349,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts\/3334\/revisions\/3349"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/media\/3335"}],"wp:attachment":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/media?parent=3334"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/categories?post=3334"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/tags?post=3334"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}