You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js使用pg-promise设置ColumnSet时出现重复连接警告

问题根因

这个警告和ColumnSet配置无关,是Next.js开发模式热重载+单例逻辑写法缺陷导致的:

  • 代码混用ES Module import和CommonJS require导入pg-promise,Next.js编译时模块缓存易失效,导致初始化逻辑重复执行
  • pg-promise实例初始化写在模块顶层,每次模块被热重载重新执行时,还没走到单例判断逻辑就已经创建了新的初始化实例,重复生成同连接的数据库对象触发警告
修复方案

1. 重写数据库单例文件

把pgp实例、数据库连接的初始化逻辑全部放到单例判断内部,统一导入方式,用全局变量直接存储单例,适配Next.js热重载机制,修正后代码如下:

import ConfigEnv from 'utils/configuration';
import pgPromise, { IDatabase, IMain } from 'pg-promise';

const initOptions = {
    capSQL: true,
};

interface IDatabaseScope {
    db: IDatabase<any>;
    pgp: IMain;
}

declare global {
    var __pgpSingleton: IDatabaseScope | undefined;
}

export function getDB(): IDatabaseScope {
    if (!global.__pgpSingleton) {
        const pgp = pgPromise(initOptions);
        const db = pgp(ConfigEnv.pgp);
        global.__pgpSingleton = { db, pgp };
    }
    return global.__pgpSingleton;
}

2. 调整API路由代码

原有API逻辑不需要大改,只需要移除冗余的Promise链式写法(已经用async/await不需要再嵌套.then),补个请求方法判断即可。ColumnSet本身是纯内存SQL生成对象,不会触发数据库连接,只需要初始化一次复用就行:

import { getDB } from 'db/pgpdb';
const { db, pgp } = getDB();

const cs = new pgp.helpers.ColumnSet([
  '?detail_id',
  'age',
  'name'
], {
  table: 'user_detail',
});

export default async (req, res) => {
  if (req.method !== 'POST') return res.status(405).end();
  
  try {
    const update = pgp.helpers.update(req.body.content, cs) + ` WHERE v.detail_id = t.detail_id`;
    await db.none(update);
    return res.status(200).end();
  } catch (error) {
    console.log('update error:', error);
    return res.status(500).send(error);
  }
};
验证说明
  • 修改完成后重启Next.js开发服务,清空之前的模块缓存,再调用接口就不会出现重复创建数据库对象的警告
  • 生产环境下Next.js不会触发热重载,单例只会初始化一次,连接池复用正常,不存在连接泄漏问题
  • ColumnSet配置本身和这个警告无关,不需要调整ColumnSet的字段定义逻辑

内容的提问来源于stack exchange,提问作者Jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:09:30