iKode Blog icon iKode Blog
返回文章列表

Article

查询队列演示:把 pg 的并发警告画成时间线

技术笔记2026年6月19日 09:152 min

同一个 PostgreSQL client 上同时发出多个查询时,真正需要理解的是连接、队列与并发之间的关系。

开发服务器曾经出现过一条 pg 弃用警告:当一个 client 还在执行查询时,又调用了 client.query()。在 pg 8 中它仍然会排队执行,但 pg 9 不再鼓励依赖这种隐式行为。

单看 warning 很容易误解成“不能并发查询”。问题其实更具体:一个 PostgreSQL client 在同一时刻只能处理一条查询。 真正的并行需要多个连接,或者由连接池分配多个 client。

查询队列演示没有真的向数据库发送请求,而是把三种执行方式建模成时间线数据:顺序 await、连接池并行、单 client 排队。每条 query 只需要记录开始位置、持续长度和是否处于等待状态。

interface QueryBar {
  id: string
  start: number
  duration: number
  queued: boolean
  color: string
}

function queryStyle(query: QueryBar) {
  return {
    left: `${query.start}%`,
    width: `${query.duration}%`,
    backgroundColor: query.color
  }
}

顺序模式最容易推理,尤其适合共享事务上下文的操作。前一个查询完成后再执行下一个,不会出现 client 正忙的问题。

const posts = await client.query(postsSql)
const comments = await client.query(commentsSql)

如果查询彼此独立,并且确实需要缩短总耗时,可以让 pool 为它们分配连接。表面上仍然是 Promise.all,但并行能力来自连接池,而不是同一个 client 突然能同时处理多条 SQL。

const [posts, comments] = await Promise.all([
  pool.query(postsSql),
  pool.query(commentsSql)
])

最值得警惕的是拿到一个 client 后直接并行调用多次 client.query()。它过去可能“能跑”,却把执行顺序交给了隐式队列。warning 的意义正是提醒我们:应该把控制流写清楚。

这个实验把抽象的连接模型变成了可移动的条形图。切换模式时,查询是在同一条轨道上依次前进,还是在多个 client 上同时开始,一眼就能看出来。

可以在 查询队列演示 重放三种时间线。

Comments

留言

需要 GitHub 登录。新评论会先进入待审核,别急,它只是先坐到门口等一会儿。

使用 GitHub 登录后可以评论。

已通过评论

0

还没有通过审核的评论。桌子很安静,第一杯茶还没端上来。