[chore] Use 'immediate' lock for sqlite transactions (#1404)

* [chore] Use 'immediate' lock for sqlite transactions

* allow 1 connection regardless of cpu amount
This commit is contained in:
tobi 2023-01-31 13:46:45 +01:00 committed by GitHub
parent eccb3800d0
commit b80be48fed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 14 deletions

View file

@ -126,7 +126,7 @@ db-tls-ca-cert: ""
# A multiplier of 8 is a sensible default, but you may wish to increase this for instances
# running on very performant hardware, or decrease it for instances using v. slow CPUs.
#
# If you set this to 0 or less, it will be adjusted to 1.
# If you set the multiplier to less than 1, only one open connection will be used regardless of cpu count.
#
# Examples: [16, 8, 10, 2]
# Default: 8

View file

@ -182,7 +182,7 @@ db-tls-ca-cert: ""
# A multiplier of 8 is a sensible default, but you may wish to increase this for instances
# running on very performant hardware, or decrease it for instances using v. slow CPUs.
#
# If you set this to 0 or less, it will be adjusted to 1.
# If you set the multiplier to less than 1, only one open connection will be used regardless of cpu count.
#
# Examples: [16, 8, 10, 2]
# Default: 8

View file

@ -256,16 +256,40 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
}
// Drop anything fancy from DB address
address = strings.Split(address, "?")[0]
address = strings.TrimPrefix(address, "file:")
address = strings.Split(address, "?")[0] // drop any provided query strings
address = strings.TrimPrefix(address, "file:") // we'll prepend this later ourselves
// Append our own SQLite preferences
// build our own SQLite preferences
prefs := []string{
// use immediate transaction lock mode to fail quickly if tx can't lock
// see https://pkg.go.dev/modernc.org/sqlite#Driver.Open
"_txlock=immediate",
}
if address == ":memory:" {
log.Warn("using sqlite in-memory mode; all data will be deleted when gts shuts down; this mode should only be used for debugging or running tests")
// Use random name for in-memory instead of ':memory:', so
// multiple in-mem databases can be created without conflict.
address = uuid.NewString()
// in-mem-specific preferences
prefs = append(prefs, []string{
"mode=memory", // indicate in-memory mode using query
"cache=shared", // shared cache so that tests don't fail
}...)
}
// rebuild address string with our derived preferences
address = "file:" + address
if address == "file::memory:" {
address = fmt.Sprintf("file:%s?mode=memory&cache=shared", uuid.NewString())
log.Infof("using in-memory database address " + address)
log.Warn("sqlite in-memory database should only be used for debugging")
for i, q := range prefs {
var prefix string
if i == 0 {
prefix = "?"
} else {
prefix = "&"
}
address += prefix + q
}
// Open new DB instance
@ -274,7 +298,7 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
if errWithCode, ok := err.(*sqlite.Error); ok {
err = errors.New(sqlite.ErrorCodeString[errWithCode.Code()])
}
return nil, fmt.Errorf("could not open sqlite db: %s", err)
return nil, fmt.Errorf("could not open sqlite db with address %s: %w", address, err)
}
// Tune db connections for sqlite, see:
@ -294,7 +318,7 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
}
return nil, fmt.Errorf("sqlite ping: %s", err)
}
log.Info("connected to SQLITE database")
log.Infof("connected to SQLITE database with address %s", address)
return conn, nil
}
@ -304,11 +328,11 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
*/
// maxOpenConns returns multiplier * GOMAXPROCS,
// clamping multiplier to 1 if it was below 1.
// returning just 1 instead if multiplier < 1.
func maxOpenConns() int {
multiplier := config.GetDbMaxOpenConnsMultiplier()
if multiplier < 1 {
multiplier = 1
return 1
}
return multiplier * runtime.GOMAXPROCS(0)
}