Skip to content

Commit

Permalink
fix(pageserver): skip existing layers for btm-gc-compaction (#8498)
Browse files Browse the repository at this point in the history
part of #8002

Due to the limitation of the current layer map implementation, we cannot
directly replace a layer. It's interpreted as an insert and a deletion,
and there will be file exist error when renaming the newly-created layer
to replace the old layer. We work around that by changing the end key of
the image layer. A long-term fix would involve a refactor around the
layer file naming. For delta layers, we simply skip layers with the same
key range produced, though it is possible to add an extra key as an
alternative solution.

* The image layer range for the layers generated from gc-compaction will
be Key::MIN..(Key..MAX-1), to avoid being recognized as an L0 delta
layer.
* Skip existing layers if it turns out that we need to generate a layer
with the same persistent key in the same generation.

Note that it is possible that the newly-generated layer has different
content from the existing layer. For example, when the user drops a
retain_lsn, the compaction could have combined or dropped some records,
therefore creating a smaller layer than the existing one. We discard the
"optimized" layer for now because we cannot deal with such rewrites
within the same generation.


---------

Signed-off-by: Alex Chi Z <[email protected]>
Co-authored-by: Christian Schwarz <[email protected]>
  • Loading branch information
skyzh and problame authored Aug 1, 2024
1 parent 970f292 commit f4a668a
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 34 deletions.
47 changes: 45 additions & 2 deletions pageserver/src/tenant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6963,7 +6963,11 @@ mod tests {
vec![
// Image layer at GC horizon
PersistentLayerKey {
key_range: Key::MIN..Key::MAX,
key_range: {
let mut key = Key::MAX;
key.field6 -= 1;
Key::MIN..key
},
lsn_range: Lsn(0x30)..Lsn(0x31),
is_delta: false
},
Expand All @@ -6982,6 +6986,15 @@ mod tests {
]
);

// increase GC horizon and compact again
{
// Update GC info
let mut guard = tline.gc_info.write().unwrap();
guard.cutoffs.time = Lsn(0x40);
guard.cutoffs.space = Lsn(0x40);
}
tline.compact_with_gc(&cancel, &ctx).await.unwrap();

Ok(())
}

Expand Down Expand Up @@ -7333,6 +7346,15 @@ mod tests {
);
}

// increase GC horizon and compact again
{
// Update GC info
let mut guard = tline.gc_info.write().unwrap();
guard.cutoffs.time = Lsn(0x40);
guard.cutoffs.space = Lsn(0x40);
}
tline.compact_with_gc(&cancel, &ctx).await.unwrap();

Ok(())
}

Expand Down Expand Up @@ -7837,6 +7859,10 @@ mod tests {
];

let verify_result = || async {
let gc_horizon = {
let gc_info = tline.gc_info.read().unwrap();
gc_info.cutoffs.time
};
for idx in 0..10 {
assert_eq!(
tline
Expand All @@ -7847,7 +7873,7 @@ mod tests {
);
assert_eq!(
tline
.get(get_key(idx as u32), Lsn(0x30), &ctx)
.get(get_key(idx as u32), gc_horizon, &ctx)
.await
.unwrap(),
&expected_result_at_gc_horizon[idx]
Expand All @@ -7873,7 +7899,24 @@ mod tests {

let cancel = CancellationToken::new();
tline.compact_with_gc(&cancel, &ctx).await.unwrap();
verify_result().await;

// compact again
tline.compact_with_gc(&cancel, &ctx).await.unwrap();
verify_result().await;

// increase GC horizon and compact again
{
// Update GC info
let mut guard = tline.gc_info.write().unwrap();
guard.cutoffs.time = Lsn(0x38);
guard.cutoffs.space = Lsn(0x38);
}
tline.compact_with_gc(&cancel, &ctx).await.unwrap();
verify_result().await; // no wals between 0x30 and 0x38, so we should obtain the same result

// not increasing the GC horizon and compact again
tline.compact_with_gc(&cancel, &ctx).await.unwrap();
verify_result().await;

Ok(())
Expand Down
14 changes: 14 additions & 0 deletions pageserver/src/tenant/storage_layer/layer_desc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ pub struct PersistentLayerKey {
pub is_delta: bool,
}

impl std::fmt::Display for PersistentLayerKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}..{} {}..{} is_delta={}",
self.key_range.start,
self.key_range.end,
self.lsn_range.start,
self.lsn_range.end,
self.is_delta
)
}
}

impl PersistentLayerDesc {
pub fn key(&self) -> PersistentLayerKey {
PersistentLayerKey {
Expand Down
Loading

1 comment on commit f4a668a

@github-actions
Copy link

Choose a reason for hiding this comment

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

2188 tests run: 2106 passed, 3 failed, 79 skipped (full report)


Failures on Postgres 14

  • test_gc_feedback_with_snapshots[github-actions-selfhosted]: release
  • test_gc_feedback[github-actions-selfhosted]: release
  • test_basebackup_with_high_slru_count[github-actions-selfhosted-10-13-30]: release
# Run all failed tests locally:
scripts/pytest -vv -n $(nproc) -k "test_gc_feedback_with_snapshots[release-pg14-github-actions-selfhosted] or test_gc_feedback[release-pg14-github-actions-selfhosted] or test_basebackup_with_high_slru_count[release-pg14-github-actions-selfhosted-10-13-30]"
Flaky tests (1)

Postgres 15

Code coverage* (full report)

  • functions: 32.9% (7125 of 21683 functions)
  • lines: 50.4% (57357 of 113719 lines)

* collected from Rust tests only


The comment gets automatically updated with the latest test results
f4a668a at 2024-08-01T17:59:41.850Z :recycle:

Please sign in to comment.