mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-21 14:46:58 +00:00
* fix(filer/postgres): use pgx v5 API for PgBouncer simple protocol
In pgx/v5 the `prefer_simple_protocol` DSN parameter was removed, so
appending it to the connection string caused PgBouncer/PostgreSQL to
reject it as an unknown startup parameter:
FATAL: unsupported startup parameter: prefer_simple_protocol (SQLSTATE 08P01)
Parse the DSN with pgx.ParseConfig and, when pgbouncer_compatible is
set, configure DefaultQueryExecMode = QueryExecModeSimpleProtocol and
disable the statement/description caches. Register the config via
stdlib.RegisterConnConfig before sql.Open.
Fixes #9005
* refactor(filer/postgres): extract shared OpenPGXDB helper with cleanup
Extract the pgx v5 ParseConfig/RegisterConnConfig/sql.Open/Ping logic
into a shared postgres.OpenPGXDB helper used by both postgres and
postgres2 filer stores, eliminating ~60 lines of duplication.
The helper also unregisters the conn config via stdlib.UnregisterConnConfig
on every failure path (sql.Open error, Ping error) so we do not leak
entries in stdlib's global connection config map when initialization
fails.
* refactor(filer/postgres): use stdlib.OpenDB to avoid conn config leak
Switch OpenPGXDB from RegisterConnConfig + sql.Open("pgx", connStr) to
stdlib.OpenDB(*connConfig). The former leaks an entry in stdlib's global
conn config map on every successful initialization; stdlib.OpenDB takes
the config directly and keeps no global registration.
Addresses CodeRabbit review feedback on #9010.
51 lines
1.7 KiB
Go
51 lines
1.7 KiB
Go
package postgres
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/stdlib"
|
|
)
|
|
|
|
// OpenPGXDB parses the given DSN into a pgx ConnConfig, applies PgBouncer
|
|
// compatibility settings when requested, opens a *sql.DB via
|
|
// stdlib.OpenDB, and verifies it with Ping.
|
|
//
|
|
// In pgx/v5 the prefer_simple_protocol DSN parameter was removed, so simple
|
|
// protocol mode must be configured on the ConnConfig via
|
|
// DefaultQueryExecMode. We use stdlib.OpenDB(config) rather than
|
|
// RegisterConnConfig + sql.Open so we don't leak entries in stdlib's global
|
|
// connection config map on either success or failure paths.
|
|
//
|
|
// adaptedSqlUrl is used only for error messages (the caller is expected to
|
|
// have redacted any password).
|
|
func OpenPGXDB(sqlUrl, adaptedSqlUrl string, pgbouncerCompatible bool, maxIdle, maxOpen, maxLifetimeSeconds int) (*sql.DB, error) {
|
|
connConfig, parseErr := pgx.ParseConfig(sqlUrl)
|
|
if parseErr != nil {
|
|
return nil, fmt.Errorf("can not parse connection config for %s error:%v", adaptedSqlUrl, parseErr)
|
|
}
|
|
|
|
// PgBouncer compatibility: use the simple query protocol and disable
|
|
// statement caching. This avoids prepared statement issues with
|
|
// PgBouncer's transaction pooling mode.
|
|
if pgbouncerCompatible {
|
|
connConfig.DefaultQueryExecMode = pgx.QueryExecModeSimpleProtocol
|
|
connConfig.StatementCacheCapacity = 0
|
|
connConfig.DescriptionCacheCapacity = 0
|
|
}
|
|
|
|
db := stdlib.OpenDB(*connConfig)
|
|
db.SetMaxIdleConns(maxIdle)
|
|
db.SetMaxOpenConns(maxOpen)
|
|
db.SetConnMaxLifetime(time.Duration(maxLifetimeSeconds) * time.Second)
|
|
|
|
if err := db.Ping(); err != nil {
|
|
db.Close()
|
|
return nil, fmt.Errorf("connect to %s error:%v", adaptedSqlUrl, err)
|
|
}
|
|
|
|
return db, nil
|
|
}
|