# Postgres Node: connection pool memory leak — evicted pools never closed

该报错是 n8n 的 Postgres 节点在非 SSH 连接分支下,连接池被淘汰(evict)时未调用 db.$pool.end() ,导致 pg-promise 的 Database 对象永久保留在进程全局注册表中,并通过闭包固定住整个执行上下文,造成内存随每次执行持续增长。优先排查是否使用了非

快速结论:该报错是 n8n 的 Postgres 节点在非 SSH 连接分支下,连接池被淘汰(evict)时未调用 db.$pool.end(),导致 pg-promise 的 Database 对象永久保留在进程全局注册表中,并通过闭包固定住整个执行上下文,造成内存随每次执行持续增长。优先排查是否使用了非 SSH 的 Postgres 节点,并升级到包含修复的 n8n 版本。

适用环境:n8n(Issue 中通过 docker compose 部署,n8n 版本 2.26.8),Postgres 节点,非 SSH 连接分支,pg-promise 数据库驱动。

最快修复方案:暂无确认的一步修复方案。官方确认问题已解决并合入修复,将在后续版本中发布;社区提交的 PR #32730 已进入合并队列,通过将 receive 回调移至模块作用域来切断执行上下文引用链。建议等待官方版本更新,或在自定义构建中合入该 PR。

注意事项:allowExitOnIdle: true 选项虽然可以让连接池空闲时自动退出,但经测试仍无法解决执行上下文被闭包引用导致的内存累积问题,不能作为修复手段。

问题场景

用户在 n8n 中使用 Postgres 节点(非 SSH 分支)执行工作流,在多次执行后通过 Chrome DevTools 连接 Node.js 调试端口(9229)抓取堆快照,观察到 Database 对象数量随执行次数线性增长且无法被垃圾回收。每次执行约可泄漏约 10 MB 内存(与上游节点输出大小成正比),长期运行会导致内存持续膨胀。

报错原文

# Postgres Node: connection pool memory leak — evicted pools never closed

堆快照中通过保留路径(retainer path)确认对象被以下引用链持有:

global[Symbol.for('pgPromiseDatabasePool')].dbs[] → Database.$config.options.receive → captured execution context

原因分析

可能原因:ConnectionPoolManager 在连接池空闲超过 5 分钟 TTL 后调用 abortController.abort() 进行淘汰,但 Postgres 节点的非 SSH 代码路径没有注册 abort 监听器,导致连接池虽然从管理器的 Map 中移除,却不会调用 db.$pool.end()Database 对象因此永久保留在 pg-promise 的进程级注册表(global[Symbol.for('pgPromiseDatabasePool')].dbs[])中。

此外,receive 回调在 configurePostgres 函数内部定义,闭包捕获了包含执行上下文(this)的外层作用域。由于 Database 对象从未被 end(),执行上下文(包括上游节点的全部 inputData)被永久固定,无法被垃圾回收。

环境排查

  • 确认 n8n 版本(Issue 验证版本为 2.26.8)
  • 确认 Postgres 节点使用的是非 SSH 连接分支(SSH 分支已正确实现 abort 监听器并调用 db.$pool.end()
  • 检查部署方式:Issue 中使用 docker compose 部署 n8n
  • 检查 n8n 使用的 pg-promise 版本(社区建议更新 pg-promise 版本,Issue 中使用的版本偏旧)
  • 确认是否能通过 Chrome DevTools 连接到 n8n 的调试端口进行堆快照分析

解决步骤

  1. 确认当前 n8n 版本是否已包含修复——官方已确认修复会合入后续版本,更新到最新版本后验证问题是否消失。
  2. 如果仍使用旧版本且暂时无法升级,可检查 n8n 的 GitHub 仓库中 PR #32730 的状态,该 PR 将 receive 回调移至模块作用域,可切断对执行上下文的引用链。可在自定义构建中合入该 PR 进行验证。
  3. 如需快速缓解(非根因修复),可尝试在数据库连接配置中添加 allowExitOnIdle: true 选项——但请注意 Issue 测试表明这只能让连接池空闲时自动退出,无法解决执行上下文被闭包引用导致的内存累积,不建议依赖此方案。
  4. 更新 pg-promise 版本(社区建议,Issue 中使用的版本过旧);这属于推测性建议,需自行评估兼容性。

验证方法

重复 Issue 中的复现步骤:激活工作流并等待执行完成后,连接 Chrome DevTools 到 localhost:9229,在 Memory 面板多次抓取堆快照,确认 Database 对象数量不再随执行次数增长;同时检查保留路径中是否已不存在 global[Symbol.for('pgPromiseDatabasePool')].dbs[]Database.$config.options.receive → 执行上下文的引用链。升级到修复版本后,多次执行工作流并对比堆快照,内存占用应保持稳定不再线性增长。

参考来源

n8n-io/n8n #32724

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 18922

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注