Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

PostgreSQL: concurrent DeleteTable calls exhaust a shared pool waiting on a second connection

未关闭
#615 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 4 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
55/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
postgresql, rust
领域
backend, databases

调研方向

Read crates/storage-postgres/src/worker_store.rs at process_transitions and crates/storage-postgres/src/lib.rs at the data_conn branch to trace when the catalog and data pools are shared. Then inspect backup_engine::restore_server_slot_count for the semaphore pattern and tests around DeleteTable and drop_table_storage. Done means concurrent calls with one database and pool size N complete promptly, with no rows left DELETING.

由索引模型根据 Issue 内容生成。

描述

backend:postgresql bug

Where

crates/storage-postgres/src/worker_store.rs, process_transitions: the pass opens a catalog transaction (self.pool.begin()), selects the candidate row, and then calls drop_table_storage(&self.data_pool, ...), which begins a second transaction on data_pool. When no separate data database is configured, data_pool is a clone of the catalog pool (crates/storage-postgres/src/lib.rs, the data_conn branch), so both transactions come from one pool.

This applies to the pass DeleteTable runs for its own table (finish_table_delete, PR #504) and to the poller pass. The poller runs one pass at a time, so it needs two connections; DeleteTable calls run concurrently, one scoped pass each.

Measured

PostgreSQL 16.15, one scratch database for catalog and data, pool_size 10, no poller running, concurrent DeleteTable calls each awaiting its scoped pass (probe kept at issues/pr-sweep-2026-10-26/504-lock-timeout/v-probe-pool.rs.txt on the development host; not part of the tree):

Concurrent DeleteTable calls Response time Rows left DELETING
5 all within 0.12 s 0
24 all 24 answered after 30.07 s 20

With more concurrent calls than the pool has connections, every connection is held by a catalog transaction waiting for a second connection that none can get, until sqlx's 30 s acquire timeout fails the drop. The clients get TableStatus: DELETING (the acquire failure takes the existing "drop failed, leave the row for the poller" path), and the poller finishes the rows once connections are free. No data is lost; the cost is 30 s of latency on each call and a pool that serves nothing else for that time.

Not measured with a separate data database, where the two pools are distinct and the deadlock cannot form.

Suggested fix

Cap concurrent scoped passes at pool_size / 2 with a semaphore taken before self.pool.begin(), which leaves each pass a connection for its second acquire; backup_engine::restore_server_slot_count does the same for restores. Alternatively, when data_pool is the catalog pool, run the drop on the catalog transaction's own connection, which is a larger change to drop_table_storage.

A test: with pool_size N and one database, issue 2N concurrent DeleteTable calls on 2N tables and assert every call returns within a few seconds and no row is left DELETING after the calls return.

主要语言
Rust
星标
517
派生
60
平均合并
4 天 10 小时
30 天内合并 PR
37

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

ExtendDB/extenddb 的其他 Issue

查看 ExtendDB/extenddb 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。