GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-134004: Dbm vacuuming by Andrea-Oliveri · Pull Request #134028 · python/cpython

Conversation

@Andrea-Oliveri

@Andrea-Oliveri Andrea-Oliveri commented May 15, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

gh-134004:

  1. Added a .reorganize() method to dbm.sqlite and dbm.dumb which allows to retrieve unused space from database files. Name was chosen for consistency with dbm.gnu.reorganize(). dbm.ndbm` does not support any such optimization.
  2. dbm.dumb.reorganize() is a new custom implementation rewriting the database file in-place and removing the gaps left by deletions, then truncating the excess.
  3. Added 3 tests to ensure .reorganize() runs as expected on all compatible dbm submodules.
  4. Updated the documentation of dbm module to include contributed methods as well as to highlight some of the limitations of the current implementations, such as lack of concurrency compatibility (for dbm.dumb) and lack of automatic reorganizing
  5. Added .reorganize() method to shelve to expose dbm's submodules methods
  6. Added documentation for shelve.reorganize()

Note: Unfortunately I did not feel comfortable changing the C code at this time, so I chose not to add an empty .reorganize() method to dbm.ndbm. This resulted in:

  1. Inconsistencies between the methods supported by dbm submodules.
  2. The added tests need to verify, using hasattr(), whether the dbm objects have the .reorganize() method and succeed early if that is not the case.
  3. The documentation clearly explains the situation described here.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

erlend-aasland reacted with thumbs up emoji kaoutamine reacted with rocket emoji
All reactions
  • 👍 1 reaction
  • 🚀 1 reaction
Andrea-Oliveri added 5 commits May 14, 2025 17:42
@Andrea-Oliveri
Added tests for vacuuming functionality of dbm
7505713
@Andrea-Oliveri
Added vacuuming logic to dbm.sqlite
1147774
@Andrea-Oliveri
Added vacuuming logic to dbm.dumb
109a378
@Andrea-Oliveri
Updated documentation of dbm
cdacb53
@Andrea-Oliveri
Adapted vacuum tests to allow for submodules missing method
02a7b8a
@Andrea-Oliveri
Andrea-Oliveri requested review from berkerpeksag, corona10, erlend-aasland and serhiy-storchaka as code owners May 15, 2025 05:39
@bedevere-app

bedevere-app Bot commented May 15, 2025

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@python-cla-bot

python-cla-bot Bot commented May 15, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot added the awaiting review label May 15, 2025
@Andrea-Oliveri
Pushing news and acks entries
dcb43a2
@Andrea-Oliveri Andrea-Oliveri changed the title gh134004: Dbm vacuuming gh-134004: Dbm vacuuming May 15, 2025
@bedevere-app bedevere-app Bot mentioned this pull request May 15, 2025
DBM Module Vacuuming #134004
Closed
Andrea-Oliveri added 7 commits May 15, 2025 07:52
@Andrea-Oliveri
Changed News entry to avoid failure during Doc testing due to referen…
89fb2db
…ce to module links not found
@Andrea-Oliveri
Changed method names from .vacuum to .reorganize in dbm.sqlite and db…
476dc55
…m.dumb for consistency with dbm.gnu. Also updated documentations and tests to reflect the change
@Andrea-Oliveri
Added .reorganize() method in shelve to expose dbm submodule's own .r…
19c0c8d
…eorganize()
@Andrea-Oliveri
Added documentation for shelve.reorganize
88b4014
@Andrea-Oliveri
Fixed link in doc
5c1d45f
@Andrea-Oliveri
Updated news
992e7aa
@Andrea-Oliveri
PR review: removed unnecessary .keys()
b96480b
Yang-Wei-Ting
Yang-Wei-Ting reviewed May 16, 2025
View reviewed changes
Comment thread Lib/dbm/dumb.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Andrea-Oliveri
Andrea-Oliveri requested a review from Yang-Wei-Ting May 16, 2025 16:25
serhiy-storchaka
serhiy-storchaka reviewed May 16, 2025
View reviewed changes

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good code.

However, there are few issues.

  • dbm.dumb does not support concurrent writing, but it supports limited concurrent access with a single writer and multiple readers. Readers may not see new data, and can read deleted data (because they cache the index), but otherwise they do not conflict with writer. But when writer calls reorganize(), it breaks readers. So using this feature can cause new bugs.

    I am not sure that we can to do something with this.

  • Other issue is that reorganize() is inherently not fail-safe. If something happens during the reorganization process, you may lose data.

Do gdbm_reorganize() and Sqlite VACUUM have the same issues or they provide some protection?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/library/dbm.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/dbm/dumb.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Andrea-Oliveri added 3 commits May 17, 2025 09:52
@Andrea-Oliveri
Updated documentation to correct notes indentation
4c23b64
@Andrea-Oliveri
Left previously removed comment as requested in PR
8a80977
@Andrea-Oliveri
Modified documentation of dbm.dumb warning to align with shelve warning
166a553
@Andrea-Oliveri

Andrea-Oliveri commented May 17, 2025

Copy link
Copy Markdown
Contributor Author

Good morning @serhiy-storchaka,
thank you very much for the review and the nice compliment 😃 .

Easy changes

I have pushed changes to address the documentation and dbm.dumb comment remarks.

Organize not being fail-safe

On the topic of reorganize() inherently being not fail-safe, I agree with you. It is my understanding that dbm.dumb does very little to be robust in general. Most notably, it relies on its __del__ method to write back, which may not always be called in case of trouble. This is why I chose this less-resource-intensive implementation over a more robust one. If we want to go for more robustness, any of these two approaches should work, although none have a 100% robustness guarantee:

  • After every block is moved in the binary file, rewrite the index
    • Advantage: keep disk space usage down
    • Disadvantage: many small writes can occur.
    • Disadvantage: If crash / KeyboardInterrupt happens between moment block is moved and index is rewritten, database is corrupt
  • Reorganize binary file in a temporary file and only once completed rename it to overwrite old version and rewrite index
    • Advantage: minimizes window of time during which db would be corrupt in case of crash
    • Disadvantage: uses more disk space.
    • Disadvantage: If crash / KeyboardInterrupt happens between when we replace old binary file with new one and moment when we replace old index file with new one, database is corrupt

Let me know how you think we should proceed. SQLITE and GDBM are designed to be much more robust and use the second technique to ensure failed reorganizations don't corrupt the database. Crucially, however, they handle a single binary file with both index and data, hence either everything is renamed atomically or nothing is.

Concurrency

My apologies, but I would disagree dbm.dumb supports any concurrency at all... I totally understand what you mean but for me if the readers can access deleted keys and if they aren't notified when a value is updated for an existing key the behaviour during concurrency is undefined, not limitedly supported.

Examples:

  • I want to update a key with a new value. In this circumstance, __setitem__ will first check if the blocks used by the previous value are more or equal than those required by the new value. If so, it makes the change in-place. Let's say the old value occupied twice as much blocks as the new value. __setitem__ will write the new value in-place, but keep the second-half of the blocks untouched. When a reader with the old index will read, he will read as many bytes as required for the old value. So he will read the new value, but also some gibblerish left out by __setitem__. This would crash modules like shelve that expect the value to be valid pickles.
  • In a similar fashion if I am updating a key with a new value larger than the old one, readers will keep reading the old value.
  • We already touched upon the deletion.

Of course this problem is well-known to any developer who looked at the source code for dbm and dbm.dumb. However, I found the documentation was a bit lackluster on these problems, so I have also updated it to warn users of these limitations (see the warning under dbm.dumb.open).

One thing that was already well explained in the documentation, however:

The shelve module does not support concurrent read/write access to shelved objects. (Multiple simultaneous read accesses are safe.) When a program has a shelf open for writing, no other program should have it open for reading or writing.

Please let me know how you would like to proceed on this issue as well.

In the meantime, have a great day! 😃

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

serhiy-storchaka
serhiy-storchaka reviewed May 28, 2025
View reviewed changes
Comment thread Lib/test/test_dbm.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Andrea-Oliveri
Skipping test instead of succeeding if method not implemented for sub…
6f34de5
…module
serhiy-storchaka
serhiy-storchaka reviewed May 28, 2025
View reviewed changes
Comment thread Lib/test/test_dbm.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@Andrea-Oliveri
Converted redundant f-string to regular string
059ad82
serhiy-storchaka
serhiy-storchaka reviewed May 28, 2025
View reviewed changes

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your response. What is left:

  • Add .. versionadded:: next for all new methods.
  • Add What's New entries.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Andrea-Oliveri added 2 commits May 28, 2025 19:33
@Andrea-Oliveri
Added versionadded to method documentations
3e7049f
@Andrea-Oliveri
Added whatsnew entries
2f5af38
serhiy-storchaka
serhiy-storchaka approved these changes May 28, 2025
View reviewed changes

@serhiy-storchaka serhiy-storchaka left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. 👍

Thank you for your contribution, @Andrea-Oliveri. Please ping me next week if I don't merge this PR before then.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Andrea-Oliveri reacted with heart emoji
All reactions
  • ❤️ 1 reaction
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting review labels May 28, 2025
@Andrea-Oliveri
Merged changes from branch main
e2370ac
@Andrea-Oliveri

Andrea-Oliveri commented May 28, 2025

Copy link
Copy Markdown
Contributor Author

Thank you @serhiy-storchaka 😄 . Just FYI, since I had merge conflicts due to the whatsnew I have merged with main between you marking as approved and me reading the message.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@serhiy-storchaka
serhiy-storchaka merged commit f806463 into python:main Jun 1, 2025
@bedevere-app bedevere-app Bot removed the awaiting merge label Jun 1, 2025
@serhiy-storchaka serhiy-storchaka linked an issue Jun 1, 2025 that may be closed by this pull request
DBM Module Vacuuming #134004
Closed
@erlend-aasland

erlend-aasland commented Jun 2, 2025

Copy link
Copy Markdown
Contributor

This is great; thanks for the proposal and implementation, @Andrea-Oliveri; thanks for managing this, @serhiy-storchaka.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Andrea-Oliveri
Andrea-Oliveri deleted the dbm-vacuum-gh134004 branch June 6, 2025 06:01
Pranjal095 pushed a commit to Pranjal095/cpython that referenced this pull request Jul 12, 2025
@Andrea-Oliveri @Pranjal095
pythongh-134004: Added the reorganize() methods to dbm.sqlite, dbm.du…
d730671
…mb and shelve (pythonGH-134028)

They are similar to the same named method in dbm.gnu.
taegyunkim pushed a commit to taegyunkim/cpython that referenced this pull request Aug 4, 2025
@Andrea-Oliveri @taegyunkim
pythongh-134004: Added the reorganize() methods to dbm.sqlite, dbm.du…
d7eb5ea
…mb and shelve (pythonGH-134028)

They are similar to the same named method in dbm.gnu.
Agent-Hellboy pushed a commit to Agent-Hellboy/cpython that referenced this pull request Aug 19, 2025
@Andrea-Oliveri @Agent-Hellboy
pythongh-134004: Added the reorganize() methods to dbm.sqlite, dbm.du…
a151caa
…mb and shelve (pythonGH-134028)

They are similar to the same named method in dbm.gnu.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@serhiy-storchaka serhiy-storchaka serhiy-storchaka approved these changes
@berkerpeksag berkerpeksag Awaiting requested review from berkerpeksag
@erlend-aasland erlend-aasland Awaiting requested review from erlend-aasland erlend-aasland is a code owner
@corona10 corona10 Awaiting requested review from corona10 corona10 is a code owner
@Yang-Wei-Ting Yang-Wei-Ting Awaiting requested review from Yang-Wei-Ting

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

DBM Module Vacuuming

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@Andrea-Oliveri @erlend-aasland @serhiy-storchaka @Yang-Wei-Ting
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.