错误:准备好的语句_*不存在

问题描述 投票:0回答:1

我 4 天都无法解决我的问题,遗憾的是,chatGPT 在这方面也很弱。

简而言之: 我有 Go、Gin-gonic v1.9.0 API,它使用 Gorm ORM v1.24.5 和托管在 Digitalocean 上的 Postgresql 服务器 v14。我还使用

pool_mode = transaction
为特定数据库启用了 PgBouncer 功能。

问题:我无法完全理解如何正确使用带有事务池模式的 Gorm ORM 来处理每个 API 请求,并在执行 sql 查询后能够返回到 pgbouncer 池的连接。我在引擎盖下使用

jackc/pgx
检查了 ORM,但该库具有
pgxpool
以及 获取和释放 连接的能力,并且我没有找到 Gorm 如何覆盖它的任何信息。

为什么要标题准备好的陈述?在我设置选项:

PrepareStmt: false
PreferSimpleProtocol: true
之前,大多数收到的错误:
prepared statement_* already exists
。 基于 PgBouncer 的文档:http://www.pgbouncer.org/faq.html#how-to-use-prepared-statements-with-transaction-pooling,不可能在事务模式下使用准备好的语句,所以我禁用它。当我部署 API(仅一个端点)与团队进行测试时,我们观察到至少每四个 sql 查询都会失败并显示
ERROR: prepared statement_6230 doesn't exists
。当我执行时:

SELECT * FROM pg_prepared_statements;

我看到一个准备好的语句列表,大约需要 30 分钟,我猜要等到连接有效为止。使用

DEALLOCATE ALL
仅删除当前语句。

我的端点和数据库连接隐藏了不相关的代码。

func main() {
   ...
   client := setupPostgresql()
   ...
    r.GET("/deploy/:id", func(c *gin.Context) {
        id := c.Param("id")
        var deploy Deploy // small model

        timeoutCtx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second)
        defer cancel()

        if err := client.WithContext(timeoutCtx).Where("id = ?", id).First(&deploy).Error; err != nil {
            if errors.Is(err, gorm.ErrRecordNotFound) {
                c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "Deploy with id: " + id + " not found"})
                return
            } else {
                log.Panic(err) // it will be covered by gin recover
            }
        }

        c.AbortWithStatusJSON(http.StatusOK, deploy)
    })
   ...
}

func setupPostgresql() *gorm.DB  {
    dsn := "host=" + AppConfig.DBHost +
        " user=" + AppConfig.DBUser +
        " password=" + AppConfig.DBPass +
        " dbname=" + AppConfig.DBName +
        " port=" + AppConfig.Port +
        " sslmode=" + AppConfig.SSL

    client, err := gorm.Open(postgres.New(postgres.Config{
        DSN:                  dsn,
        PreferSimpleProtocol: true,
    }), &gorm.Config{
        SkipDefaultTransaction: false,
        DisableAutomaticPing:   true,
        PrepareStmt:            false,
        NowFunc: func() time.Time {
            return time.Now().UTC()
        },
        Logger: logger.Default.LogMode(logger.Silent),
    })

    ...
    underlyingDB, _ := client.DB()
    underlyingDB.SetMaxIdleConns(11)
    underlyingDB.SetMaxOpenConns(11)
    underlyingDB.SetConnMaxIdleTime(15 * time.Minute)
    underlyingDB.SetConnMaxLifetime(30 * time.Minute)
    return client
}

Infrastructure example 我希望正确配置 Gorm ORM 以在事务模式下使用 PgBouncer。

postgresql go go-gorm go-gin pgbouncer
1个回答
0
投票

db, err := gorm.Open(postgres.New(postgres.Config{ DSN:DSN, 首选简单协议:true, }), &gorm.Config{ 命名策略: schema.NamingStrategy{ 表前缀:“wa.”, 奇异表:假, }, })

© www.soinside.com 2019 - 2024. All rights reserved.