#12874·neon

[错误]: 通过 `gc_compaction_layer_update_lock` 在 I/O 层中,页面服务器读取路径出现层级优先级死锁

作者: YZL0v3ZZ创建于 2026年3月28日更新于 2026年8月26日
标签t/bug

代码片段(读路径 — get_vectored_reconstruct_data_timeline):

rust
// 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