Go语言 错误:准备语句_* 不存在

vkc1a9a2  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(109)

我是4天不能解决我的问题,可悲的是,但chatGPT也弱在这方面。

**简而言之:**我有Go,Gin-gonic v1.9.0 API,使用Gorm ORM v1.24.5和Postgresql server v14托管在Digitalocean上。我还为特定的数据库启用了pool_mode = transaction的PgBouncer特性。
问题:我不能完全理解我应该如何正确使用Gorm ORM与事务池模式来处理每个API请求,并在执行SQL查询后能够返回连接到pgbouncer池。我检查了ORM使用jackc/pgx的引擎盖下,但该库有pgxpool和能力 * 获取和释放 * 连接,我没有找到任何信息Gorm如何涵盖它。
**为什麽要写文章?**在设置选项之前:PrepareStmt: falsePreferSimpleProtocol: true,主要接收错误:prepared statement_* already exists。基于PgBouncer的文档:http://www.pgbouncer.org/faq.html#how-to-use-prepared-statements-with-transaction-pooling,在transaction模式下不可能使用prepared statements,所以我禁用了它。当我部署我的API(只有一个端点)与一个团队一起测试时,我们观察到使用ERROR: prepared statement_6230 doesn't exists时,至少有四分之一的sql查询失败。当我被处决时:

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。

ktecyv1j

ktecyv1j1#

db, err := gorm.Open(postgres.New(postgres.Config{
        DSN:                  dsn,
        **PreferSimpleProtocol: true,**
    }), &gorm.Config{
        NamingStrategy: schema.NamingStrategy{
            TablePrefix:   "wa.",
            SingularTable: false,
        },
    })

相关问题