-
Notifications
You must be signed in to change notification settings - Fork 2.2k
multi: change sql db default max connections #10426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,12 +7,19 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // defaultMaxConns is the number of permitted active and idle | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // defaultMaxConnsPostgres is the number of permitted active and idle | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // connections. We want to limit this so it isn't unlimited. We use the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // same value for the number of idle connections as, this can speed up | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // queries given a new connection doesn't need to be established each | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // time. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultMaxConns = 25 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultMaxConnsPostgres = 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // defaultMaxConnsSqlite is the number of permitted active and idle | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // connections. We want to limit this to 2 because SQLite allows for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // concurrent reads however writers are limited to 1 so we select 2 here | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // to allow for concurrent reads but keep the number of connections low | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // to avoid write contention. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultMaxConnsSqlite = 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid duplicating these default values in the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // connIdleLifetime is the amount of time a connection can be idle. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| connIdleLifetime = 5 * time.Minute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,13 @@ import ( | |
| "context" | ||
| "database/sql" | ||
| "fmt" | ||
| "io/fs" | ||
| "net/url" | ||
| "path" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "github.com/golang-migrate/migrate/v4/database" | ||
| pgx_migrate "github.com/golang-migrate/migrate/v4/database/pgx/v5" | ||
| _ "github.com/golang-migrate/migrate/v4/source/file" // Read migrations from files. // nolint:ll | ||
| _ "github.com/jackc/pgx/v5" | ||
|
|
@@ -122,7 +124,7 @@ func NewPostgresStore(cfg *PostgresConfig) (*PostgresStore, error) { | |
| err) | ||
| } | ||
|
|
||
| maxConns := defaultMaxConns | ||
| maxConns := defaultMaxConnsPostgres | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| if cfg.MaxConnections > 0 { | ||
| maxConns = cfg.MaxConnections | ||
| } | ||
|
|
@@ -148,6 +150,33 @@ func (s *PostgresStore) GetBaseDB() *BaseDB { | |
| return s.BaseDB | ||
| } | ||
|
|
||
| // postgresMigrationExecutor implements MigrationExecutor using a single reusable | ||
| // migrate driver to avoid holding multiple database connections. | ||
| type postgresMigrationExecutor struct { | ||
| driver database.Driver | ||
| dbName string | ||
| fs fs.FS | ||
| } | ||
|
|
||
| // ExecuteMigrations runs migrations using the pre-created driver. | ||
| func (p *postgresMigrationExecutor) ExecuteMigrations(target MigrationTarget) error { | ||
| return applyMigrations(p.fs, p.driver, "sqlc/migrations", p.dbName, target) | ||
| } | ||
|
|
||
| // GetSchemaVersion returns the current schema version using the pre-created driver. | ||
| func (p *postgresMigrationExecutor) GetSchemaVersion() (int, bool, error) { | ||
| version, dirty, err := p.driver.Version() | ||
| if err != nil { | ||
| return 0, false, err | ||
| } | ||
| return version, dirty, nil | ||
| } | ||
|
|
||
| // SetSchemaVersion sets the schema version using the pre-created driver. | ||
| func (p *postgresMigrationExecutor) SetSchemaVersion(version int, dirty bool) error { | ||
| return p.driver.SetVersion(version, dirty) | ||
| } | ||
|
|
||
| // ApplyAllMigrations applies both the SQLC and custom in-code migrations to the | ||
| // Postgres database. | ||
| func (s *PostgresStore) ApplyAllMigrations(ctx context.Context, | ||
|
|
@@ -158,7 +187,30 @@ func (s *PostgresStore) ApplyAllMigrations(ctx context.Context, | |
| return nil | ||
| } | ||
|
|
||
| return ApplyMigrations(ctx, s.BaseDB, s, migrations) | ||
| // Create a single migrate driver that will be reused for all migration | ||
| // operations to avoid holding multiple database connections. | ||
| dbName, err := getDatabaseNameFromDSN(s.cfg.Dsn) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| driver, err := pgx_migrate.WithInstance(s.DB, &pgx_migrate.Config{}) | ||
| if err != nil { | ||
| return errPostgresMigration(err) | ||
| } | ||
|
|
||
| // Note: We don't call driver.Close() here because it closes the | ||
| // underlying *sql.DB. The single connection held by the driver will | ||
| // be cleaned up when the *sql.DB is closed. | ||
|
|
||
| // Create a migration executor that reuses this driver. | ||
| executor := &postgresMigrationExecutor{ | ||
| driver: driver, | ||
| dbName: dbName, | ||
| fs: newReplacerFS(sqlSchemas, postgresSchemaReplacements), | ||
| } | ||
|
|
||
| return ApplyMigrations(ctx, s.BaseDB, executor, migrations) | ||
| } | ||
|
|
||
| func errPostgresMigration(err error) error { | ||
|
|
@@ -178,6 +230,10 @@ func (s *PostgresStore) ExecuteMigrations(target MigrationTarget) error { | |
| return errPostgresMigration(err) | ||
| } | ||
|
|
||
| // Note: We don't call driver.Close() here because it closes the | ||
| // underlying *sql.DB. The connection held by the driver will be | ||
| // cleaned up when the *sql.DB is closed. | ||
|
|
||
| // Populate the database with our set of schemas based on our embedded | ||
| // in-memory file system. | ||
| postgresFS := newReplacerFS(sqlSchemas, postgresSchemaReplacements) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,10 +6,12 @@ import ( | |
| "context" | ||
| "database/sql" | ||
| "fmt" | ||
| "io/fs" | ||
| "net/url" | ||
| "path/filepath" | ||
| "testing" | ||
|
|
||
| "github.com/golang-migrate/migrate/v4/database" | ||
| sqlite_migrate "github.com/golang-migrate/migrate/v4/database/sqlite" | ||
| "github.com/lightningnetwork/lnd/sqldb/sqlc" | ||
| "github.com/stretchr/testify/require" | ||
|
|
@@ -130,8 +132,13 @@ func NewSqliteStore(cfg *SqliteConfig, dbPath string) (*SqliteStore, error) { | |
| err) | ||
| } | ||
|
|
||
| db.SetMaxOpenConns(defaultMaxConns) | ||
| db.SetMaxIdleConns(defaultMaxConns) | ||
| maxConns := defaultMaxConnsSqlite | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| if cfg.MaxConnections > 0 { | ||
| maxConns = cfg.MaxConnections | ||
| } | ||
|
|
||
| db.SetMaxOpenConns(maxConns) | ||
| db.SetMaxIdleConns(maxConns) | ||
| db.SetConnMaxLifetime(connIdleLifetime) | ||
| queries := sqlc.New(db) | ||
|
|
||
|
|
@@ -152,6 +159,32 @@ func (s *SqliteStore) GetBaseDB() *BaseDB { | |
| return s.BaseDB | ||
| } | ||
|
|
||
| // sqliteMigrationExecutor implements MigrationExecutor using a single reusable | ||
| // migrate driver to avoid holding multiple database connections. | ||
| type sqliteMigrationExecutor struct { | ||
| driver database.Driver | ||
| fs fs.FS | ||
| } | ||
|
|
||
| // ExecuteMigrations runs migrations using the pre-created driver. | ||
| func (s *sqliteMigrationExecutor) ExecuteMigrations(target MigrationTarget) error { | ||
| return applyMigrations(s.fs, s.driver, "sqlc/migrations", "sqlite", target) | ||
| } | ||
|
|
||
| // GetSchemaVersion returns the current schema version using the pre-created driver. | ||
| func (s *sqliteMigrationExecutor) GetSchemaVersion() (int, bool, error) { | ||
| version, dirty, err := s.driver.Version() | ||
| if err != nil { | ||
| return 0, dirty, err | ||
| } | ||
| return version, dirty, nil | ||
| } | ||
|
|
||
| // SetSchemaVersion sets the schema version using the pre-created driver. | ||
| func (s *sqliteMigrationExecutor) SetSchemaVersion(version int, dirty bool) error { | ||
| return s.driver.SetVersion(version, dirty) | ||
| } | ||
|
|
||
| // ApplyAllMigrations applies both the SQLC and custom in-code migrations to the | ||
| // SQLite database. | ||
| func (s *SqliteStore) ApplyAllMigrations(ctx context.Context, | ||
|
|
@@ -162,7 +195,26 @@ func (s *SqliteStore) ApplyAllMigrations(ctx context.Context, | |
| return nil | ||
| } | ||
|
|
||
| return ApplyMigrations(ctx, s.BaseDB, s, migrations) | ||
| // Create a single migrate driver that will be reused for all migration | ||
| // operations to avoid holding multiple database connections. | ||
| driver, err := sqlite_migrate.WithInstance( | ||
| s.DB, &sqlite_migrate.Config{}, | ||
| ) | ||
| if err != nil { | ||
| return errSqliteMigration(err) | ||
| } | ||
|
|
||
| // Note: We don't call driver.Close() here because it closes the | ||
| // underlying *sql.DB. The single connection held by the driver will | ||
| // be cleaned up when the *sql.DB is closed. | ||
|
|
||
| // Create a migration executor that reuses this driver. | ||
| executor := &sqliteMigrationExecutor{ | ||
| driver: driver, | ||
| fs: newReplacerFS(sqlSchemas, sqliteSchemaReplacements), | ||
| } | ||
|
|
||
| return ApplyMigrations(ctx, s.BaseDB, executor, migrations) | ||
| } | ||
|
|
||
| func errSqliteMigration(err error) error { | ||
|
|
@@ -179,6 +231,10 @@ func (s *SqliteStore) ExecuteMigrations(target MigrationTarget) error { | |
| return errSqliteMigration(err) | ||
| } | ||
|
|
||
| // Note: We intentionally don't call driver.Close() here because it would | ||
| // close the underlying *sql.DB that we passed to WithInstance. The | ||
| // driver will be cleaned up when the *sql.DB is closed. | ||
|
|
||
| // Populate the database with our set of schemas based on our embedded | ||
| // in-memory file system. | ||
| sqliteFS := newReplacerFS(sqlSchemas, sqliteSchemaReplacements) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid duplication and ensure consistency, these default values should be sourced from the
sqldbpackage where they are also defined.