Skip to content

Conversation

@gefjon
Copy link
Contributor

@gefjon gefjon commented May 20, 2025

Description of Changes

Fixes #2758 .

Prior to this commit, system sequences (as in, sequences for columns of system tables) were not being correctly re-initialized after replaying from a commitlog. The reproducer for this was to delete the zero snapshot and then replay, and then to advance the sequence by publishing a new module version with a new table.

The difference which hid this bug was that, specifically when replaying from nothing, we begin by calling Locking::bootstrap, which will build_sequence_state, and then after replaying the commitlog,
we rebuild_state_after_replay, which will build_sequence_state again. When replaying from a snapshot, we bypass bootstrap, and so the only call to build_sequence_state is in rebuild_state_after_replay after replaying the suffix of the commitlog.

The problem was that, prior to this commit,
build_sequence_state did not fully overwrite the in-memory sequence state. If an in-memory Sequence already existed in the SequencesState, build_sequence_state would reset that sequence's value, but not its allocation. Such a pre-existing in-memory Sequence could only exist (1) for system sequences and (2) when replaying without a snapshot.
If either of these conditions were not met, no Sequence object would yet exist, and so build_sequence_state would install all of the values from the on-disk state.

The fix is simple: unconditionally clobber the in-memory Sequence state during build_sequence_state, always using the values from the committed state.

API and ABI breaking changes

N/a

Expected complexity level and risk

2-ish? Sequences and replay are tricky, but I am very confident in this change; using the committed sequence state when building the in-memory sequence state seems obviously correct.

Testing

Fixes #2758 .

Prior to this commit, system sequences (as in, sequences for columns of system tables)
were not being correctly re-initialized after replaying from a commitlog.
The reproducer for this was to delete the zero snapshot and then replay,
and then to advance the sequence  by publishing a new module version with a new table.

The difference which hid this bug was that, specifically when replaying from nothing,
we begin by calling `Locking::bootstrap`, which will `build_sequence_state`,
and then after replaying the commitlog,
we `rebuild_state_after_replay`, which will `build_sequence_state` again.
When replaying from a snapshot, we bypass `bootstrap`,
and so the only call to `build_sequence_state` is in `rebuild_state_after_replay`
after replaying the suffix of the commitlog.

The problem was that, prior to this commit,
`build_sequence_state` did not fully overwrite the in-memory sequence state.
If an in-memory `Sequence` already existed in the `SequencesState`,
`build_sequence_state` would reset that sequence's `value`, but not its `allocation`.
Such a pre-existing in-memory `Sequence` could only exist (1) for system sequences
and (2) when replaying without a snapshot.
If either of these conditions were not met, no `Sequence` object would yet exist,
and so `build_sequence_state` would install all of the values from the on-disk state.

The fix is simple: unconditionally clobber the in-memory `Sequence` state
during `build_sequence_state`, always using the values from the committed state.
@gefjon gefjon requested a review from kim May 20, 2025 15:08
I also ran this same test on master, and it failed there.
@gefjon gefjon added this pull request to the merge queue May 20, 2025
Merged via the queue into master with commit 68765f9 May 20, 2025
31 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sequences not correctly initialized after restart without snapshot

3 participants