Skip to content

Commit 03456f7

Browse files
committed
[*] set lock_timeout via connection RuntimeParams instead of per-query transaction
Reduces metric queries from 4 roundtrips (BEGIN/SET/query/COMMIT) to 1 by setting lock_timeout at connection level via pgx RuntimeParams. - Add --conn-lock-timeout option (default: 100ms, env: PW_CONN_LOCK_TIMEOUT) - Set lock_timeout in RuntimeParams for PostgreSQL sources on connect - Simplify QueryMeasurements by removing transaction wrapper - Set to "0" to disable lock_timeout Ref: https://brandur.org/fragments/postgres-parameters
1 parent 3ca7293 commit 03456f7

File tree

3 files changed

+10
-19
lines changed

3 files changed

+10
-19
lines changed

internal/reaper/database.go

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"strings"
99
"time"
1010

11-
"github.com/cybertec-postgresql/pgwatch/v3/internal/db"
1211
"github.com/cybertec-postgresql/pgwatch/v3/internal/log"
1312
"github.com/cybertec-postgresql/pgwatch/v3/internal/metrics"
1413
"github.com/cybertec-postgresql/pgwatch/v3/internal/sinks"
@@ -17,30 +16,16 @@ import (
1716
)
1817

1918
func QueryMeasurements(ctx context.Context, md *sources.SourceConn, sql string, args ...any) (metrics.Measurements, error) {
20-
var conn db.PgxIface
21-
var err error
22-
var tx pgx.Tx
2319
if strings.TrimSpace(sql) == "" {
2420
return nil, errors.New("empty SQL")
2521
}
2622

27-
conn = md.Conn
28-
if md.IsPostgresSource() {
29-
// we don't want transaction for non-postgres sources, e.g. pgbouncer
30-
if tx, err = conn.Begin(ctx); err != nil {
31-
return nil, err
32-
}
33-
defer func() { _ = tx.Commit(ctx) }()
34-
_, err = tx.Exec(ctx, "SET LOCAL lock_timeout TO '100ms'")
35-
if err != nil {
36-
return nil, err
37-
}
38-
conn = tx
39-
} else {
40-
// we want simple protocol for non-postgres connections, e.g. pgpool
23+
// For non-postgres connections (e.g. pgbouncer, pgpool), use simple protocol
24+
if !md.IsPostgresSource() {
4125
args = append([]any{pgx.QueryExecModeSimpleProtocol}, args...)
4226
}
43-
rows, err := conn.Query(ctx, sql, args...)
27+
// lock_timeout is set at connection level via RuntimeParams, no need for transaction wrapper
28+
rows, err := md.Conn.Query(ctx, sql, args...)
4429
if err == nil {
4530
return pgx.CollectRows(rows, metrics.RowToMeasurement)
4631
}

internal/sources/cmdopts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ type CmdOpts struct {
99
MaxParallelConnectionsPerDb int `long:"max-parallel-connections-per-db" mapstructure:"max-parallel-connections-per-db" description:"Max parallel metric fetches per DB. Note the multiplication effect on multi-DB instances" env:"PW_MAX_PARALLEL_CONNECTIONS_PER_DB" default:"4"`
1010
TryCreateListedExtsIfMissing string `long:"try-create-listed-exts-if-missing" mapstructure:"try-create-listed-exts-if-missing" description:"Try creating the listed extensions (comma sep.) on first connect for all monitored DBs when missing. Main usage - pg_stat_statements" env:"PW_TRY_CREATE_LISTED_EXTS_IF_MISSING" default:""`
1111
CreateHelpers bool `long:"create-helpers" mapstructure:"create-helpers" description:"Create helper database objects from metric definitions" env:"PW_CREATE_HELPERS"`
12+
ConnLockTimeout string `long:"conn-lock-timeout" mapstructure:"conn-lock-timeout" description:"PostgreSQL lock_timeout for metric query connections. Set to 0 to disable" env:"PW_CONN_LOCK_TIMEOUT" default:"100ms"`
1213
}

internal/sources/conn.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ func (md *SourceConn) Connect(ctx context.Context, opts CmdOpts) (err error) {
8989
if opts.MaxParallelConnectionsPerDb > 0 {
9090
md.ConnConfig.MaxConns = int32(opts.MaxParallelConnectionsPerDb)
9191
}
92+
// Set lock_timeout at connection level for PostgreSQL sources to avoid
93+
// wrapping every query in a transaction with SET LOCAL lock_timeout
94+
if md.IsPostgresSource() && opts.ConnLockTimeout != "" && opts.ConnLockTimeout != "0" {
95+
md.ConnConfig.ConnConfig.RuntimeParams["lock_timeout"] = opts.ConnLockTimeout
96+
}
9297
md.Conn, err = NewConnWithConfig(ctx, md.ConnConfig)
9398
if err != nil {
9499
return err

0 commit comments

Comments
 (0)