Strapi v4+Postgres+Heroku运行npm run develop报Knex连接超时错误
问题场景
基于Strapi v4搭建、采用PostgreSQL作为数据库、部署于Heroku平台的项目,执行npm run develop启动开发环境时抛出如下报错:
Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
排查步骤
- 核对数据库连通性与基础配置:检查项目数据库配置文件(
config/database.js或TS项目的config/database.ts)中Heroku Postgres连接参数是否正确,确认本地网络可正常访问Heroku Postgres服务、本地出口IP已加入数据库访问白名单;注意Heroku免费层Postgres存在30分钟无访问自动休眠的机制,休眠状态下首次建立连接耗时会显著变长,很容易触发连接超时;同时核对DATABASE_URL连接串格式,部分低版本pg驱动解析连接串自带的sslmode=require参数时会出现连接挂起,导致连接一直被占用无法释放。 - 检查连接池配置合理性:Strapi v4默认给Knex设置的连接池上限为10,但Heroku免费层Postgres仅支持最高20个并发连接,若同时存在多个Strapi进程、数据库GUI工具(pgAdmin、DBeaver等)连接、其他服务占用连接,很容易打满连接池;另外如果配置中连接池
min参数大于0,服务启动时会预先建立常驻连接,一旦连接因网络问题断开未被回收,会持续占用连接池容量。 - 排查代码中未正常释放的连接:检查自定义插件、自定义路由中的数据库操作逻辑,确认所有事务操作都正确绑定了
.transacting(trx),不存在事务开启后未正常提交/回滚、连接泄漏的问题。 - 检查僵尸连接:通过Heroku CLI执行
heroku pg:info查看当前Postgres实例的活跃连接数,如果连接数达到实例上限,执行heroku pg:killall杀掉所有残留僵尸连接后再尝试启动服务。
解决方案
- 调整连接池配置适配Heroku Postgres限制,修改数据库配置文件的pool参数,参考配置如下:
module.exports = ({ env }) => ({ connection: { client: 'postgres', connection: { connectionString: env('DATABASE_URL'), ssl: { rejectUnauthorized: false, // Heroku Postgres 连接要求开启SSL,关闭自签名证书校验 }, }, pool: { min: 0, // 最小连接数设为0,不预占常驻连接 max: 2, // 本地开发环境最大连接数设为2,避免打满Heroku Postgres连接上限 acquireTimeoutMillis: 60000, // 连接获取超时拉长到60秒,覆盖数据库休眠唤醒的等待时长 idleTimeoutMillis: 30000, // 空闲连接30秒自动释放 reapIntervalMillis: 1000, // 每秒扫描一次可回收的空闲连接 }, debug: false, }, });
- 本地开发环境优先使用本地部署的PostgreSQL实例,不要直连Heroku上的数据库实例,从根源上规避网络波动、连接数抢占、跨网连接超时的问题。
- 启动开发服务前先清理残留Node进程,Windows环境执行
taskkill /im node.exe /f,Mac/Linux环境执行pkill node,避免之前崩溃残留的进程持续占用数据库连接。 - 规范事务写法,所有事务操作必须包裹try/catch逻辑,保证异常时连接能正常回滚释放,参考写法如下:
const trx = await strapi.db.connection.transaction(); try { // 所有事务内的数据库操作必须绑定trx await strapi.db.connection('target_table').insert(insertData).transacting(trx); await strapi.db.connection('target_table').where({ id: queryId }).update(updateData).transacting(trx); await trx.commit(); } catch (err) { await trx.rollback(); throw err; }
- 若因Heroku Postgres休眠触发报错,先通过Heroku控制台进入数据库详情页、或执行
heroku pg:info命令触发数据库实例唤醒,等待10秒左右再启动本地开发服务。
内容的提问来源于stack exchange,提问作者mohamed benkhemis
相关产品推荐
相关产品推荐

