Skip to content

WAL checkpoint can drop series references still needed for samples kept in checkpoint #16859

Description

@pr00se

Context

wlog.Checkpoint takes several parameters which govern the checkpointing process:

  • mint is the timestamp at which the WAL is being truncated
  • first is the id number of the first non-checkpoint WAL segment
  • last is the id number of the last WAL segment that will be included in the checkpoint
  • keep is a function that takes a series ref and last and returns whether the series record is still necessary after WAL segment last is deleted

The checkpoint process then scans through the old checkpoint and WAL segments [first, last] and:

  • for each series encountered, writes it into the new checkpoint if keep returns true, and drops it otherwise
  • for each other type of record encountered, writes the samples/histograms/etc. into the new checkpoint if their timestamp is > mint, and drops it otherwise

Lastly it deletes WAL segments [first, last] from disk.

Issue

WAL segments are not time aligned, so mint will almost always fall in the middle of the timerange contained within some WAL segment. (In fact, WAL segments are not guaranteed to be non-overlapping, so it's possible for mint to fall in the middle of multiple WAL segment timeranges).

The problem occurs if a series is marked as not necessary after a WAL segment X (keep for the series returns false), but some samples for that series appear in segment X with timestamps > mint. The checkpoint will throw away the series reference, but copy over the samples > mint. The next time the WAL is replayed those samples will be missing a series reference and will be dropped.

Example

Details from an occurance in a production system:

  • series foo that has samples in the WAL through segment 3108, the last one at ts = 08:00:00.087Z
  • the WAL segments contains records with the following time ranges:
    ...
    segment 3106 has samples from 07:48:00Z to 07:56:09Z
    segment 3107 has samples from 07:51:00Z to 07:59:25Z
    segment 3108 has samples from 07:55:00Z to 08:00:04Z
    ...
    
  • the checkpoint runs with:
    • mint = 08:00:00Z
    • last = 3110

The result is that the series record for foo is dropped but the sample at ts = 08:00:00.087Z is written into the checkpoint.

I've written a unit test that demonstrates this here. You can see the failure here.


In practice, #12286 actually prevents this from happening for series that are deleted from the head during routine garbage collection. However, since #16060 duplicate series encountered during WAL replay are similarly marked as "deleted" with their expiries set much closer to the actual WAL segment their final samples exist in, making this issue more likely to occur.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions