[错误]: 通过 `gc_compaction_layer_update_lock` 在 I/O 层中,页面服务器读取路径出现层级优先级死锁
作者: YZL0v3ZZ创建于 2026年3月28日更新于 2026年8月26日
标签t/bug
代码片段(读路径 — get_vectored_reconstruct_data_timeline):
// pageserver/src/tenant/timeline.rs:4670-4756
async fn get_vectored_reconstruct_data_timeline(
timeline: &Timeline,
query: &VersionedKeySpaceQuery,
reconstruct_state: &mut ValuesReconstructState,
cancel: &CancellationToken,
ctx: &RequestContext,
) -> Result<TimelineVisitOutcome, GetVectoredError> {
let _gc_cutoff_holder = timeline.get_applied_gc_cutoff_lsn();
// Line 4685: DANGER: Read guard acquired here
let _guard = timeline.gc_compaction_layer_update_lock.read().await;
// Line 4688: Layer traversal begins — involves unbounded I/O
let mut fringe = timeline.get_vectored_init_fringe(query).await?;
while let Some((layer_to_read, keyspace_to_read, lsn_range)) = fringe.next_layer() {
// Line 4704-4711: DANGER: Awaiting disk/network I/O while holding ReadGuard
layer_to_read
.get_values_reconstruct_data(
keyspace_to_read.clone(),
lsn_range,
reconstruct_state,
ctx,
)
.await?;
// Line 4735: Additional lock acquisition within the same guard scope
if !unmapped_keyspace.is_empty() {
let guard = timeline.layers.read(LayerManagerLockHolder::GetPage).await;
guard.update_search_fringe(&unmapped_keyspace, cont_lsn, &mut fringe)?;
}
}
// _guard dropped here — read lock held for ENTIRE layer traversal
}
### 代码片段(写路径 — `compact_with_gc_inner`):
```Rust
// pageserver/src/tenant/timeline/compaction.rs:4143
// 此处请求写锁在同一个 RwLock 上
let update_guard = self.gc_compaction_layer_update_lock.write().await;
// 获取更新守护,确保当前的读操作结束,新的读操作被阻塞。
let mut guard = self.layers.write(LayerManagerLockHolder::GarbageCollection).await;
…内容来源: neondatabase/neon