Keep the delete blocks of an unchanged table in use without rewriting them by ywelsch · Pull Request #25971 · duckdb/duckdb · GitHub
Skip to content

Keep the delete blocks of an unchanged table in use without rewriting them - #25971

Merged
Mytherin merged 2 commits into
duckdb:v1.5-variegatafrom
ywelsch:yw/unchanged-table-delete-blocks-1.5
Sep 21, 2026
Merged

Mytherin merged 2 commits into
duckdb:v1.5-variegatafrom
ywelsch:yw/unchanged-table-delete-blocks-1.5

Conversation

@ywelsch

@ywelsch ywelsch commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

This is a 1.5 backport for #25970

When a table's metadata is reused because none of its row groups changed, the checkpoint called CheckpointDeletes on every row group only to mark the row group's delete blocks as still in use. That serializes the version info if a delete committed after the row group was found unchanged, which is possible because commits do not wait for a checkpoint: it writes new delete blocks with the same content (the commit lies above the checkpoint's visibility bound), discards them, and leaves the old blocks, which the reused metadata still references, without the in-use mark. The checkpoint frees them, and once anything reuses them the table cannot be loaded anymore: replaying the WAL fails with "Pinning block 315.39 but it is marked as a free block".

The unchanged path now only marks the persisted delete blocks in use (RowGroup::GetPersistedDeletePointers) and never serializes; the delete that committed meanwhile is written by the next checkpoint. That is also why RowVersionManager::GetStoragePointers no longer asserts that no delete commit is pending: the blocks it returns are the ones the last checkpoint wrote, a pending commit changes nothing until the next one.

This is the minimal fix for the release branch. #25970 fixes the same problem on v2.0 in the version manager itself, by letting a checkpoint ignore deletes that committed above its bound.

debug_checkpoint_scan_sleep_ms makes a checkpoint sleep after it has
written a table's row groups and before it installs them, so that tests
can commit alongside a checkpoint at a known point.
… them

This is a 1.5 backport for duckdb#25970

When a table's metadata is reused because none of its row groups changed, the checkpoint called CheckpointDeletes on every row group only
to mark the row group's delete blocks as still in use. That serializes the version info if a delete committed after the row group was found
unchanged, which is possible because commits do not wait for a checkpoint: it writes new delete blocks with the same content (the
commit lies above the checkpoint's visibility bound), discards them, and leaves the old blocks, which the reused metadata still references,
without the in-use mark. The checkpoint frees them, and once anything reuses them the table cannot be loaded anymore: replaying the WAL fails with "Pinning block 315.39 but it is marked as a free block".

The unchanged path now only marks the persisted delete blocks in use (RowGroup::GetPersistedDeletePointers) and never serializes; the delete
that committed meanwhile is written by the next checkpoint. That is also why RowVersionManager::GetStoragePointers no longer asserts that no
delete commit is pending: the blocks it returns are the ones the last checkpoint wrote, a pending commit changes nothing until the next one.

This is the minimal fix for the release branch. duckdb#25970 fixes the same problem on v2.0 in the version manager itself, by letting
a checkpoint ignore deletes that committed above its bound.
@duckdb-draftbot
duckdb-draftbot marked this pull request as draft September 21, 2026 08:34
@ywelsch
ywelsch marked this pull request as ready for review September 21, 2026 08:37
@Mytherin
Mytherin merged commit 2c716c3 into duckdb:v1.5-variegata Sep 21, 2026
118 of 150 checks passed
@Mytherin

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants