我是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: false
和PreferSimpleProtocol: 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。
1条答案
按热度按时间ktecyv1j1#