[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:
parent
eccb3800d0
commit
b80be48fed
|
@ -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
|
# 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.
|
# 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]
|
# Examples: [16, 8, 10, 2]
|
||||||
# Default: 8
|
# Default: 8
|
||||||
|
|
|
@ -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
|
# 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.
|
# 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]
|
# Examples: [16, 8, 10, 2]
|
||||||
# Default: 8
|
# Default: 8
|
||||||
|
|
|
@ -256,16 +256,40 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop anything fancy from DB address
|
// Drop anything fancy from DB address
|
||||||
address = strings.Split(address, "?")[0]
|
address = strings.Split(address, "?")[0] // drop any provided query strings
|
||||||
address = strings.TrimPrefix(address, "file:")
|
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
|
address = "file:" + address
|
||||||
|
for i, q := range prefs {
|
||||||
if address == "file::memory:" {
|
var prefix string
|
||||||
address = fmt.Sprintf("file:%s?mode=memory&cache=shared", uuid.NewString())
|
if i == 0 {
|
||||||
log.Infof("using in-memory database address " + address)
|
prefix = "?"
|
||||||
log.Warn("sqlite in-memory database should only be used for debugging")
|
} else {
|
||||||
|
prefix = "&"
|
||||||
|
}
|
||||||
|
address += prefix + q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open new DB instance
|
// Open new DB instance
|
||||||
|
@ -274,7 +298,7 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
|
||||||
if errWithCode, ok := err.(*sqlite.Error); ok {
|
if errWithCode, ok := err.(*sqlite.Error); ok {
|
||||||
err = errors.New(sqlite.ErrorCodeString[errWithCode.Code()])
|
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:
|
// 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)
|
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
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
@ -304,11 +328,11 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// maxOpenConns returns multiplier * GOMAXPROCS,
|
// maxOpenConns returns multiplier * GOMAXPROCS,
|
||||||
// clamping multiplier to 1 if it was below 1.
|
// returning just 1 instead if multiplier < 1.
|
||||||
func maxOpenConns() int {
|
func maxOpenConns() int {
|
||||||
multiplier := config.GetDbMaxOpenConnsMultiplier()
|
multiplier := config.GetDbMaxOpenConnsMultiplier()
|
||||||
if multiplier < 1 {
|
if multiplier < 1 {
|
||||||
multiplier = 1
|
return 1
|
||||||
}
|
}
|
||||||
return multiplier * runtime.GOMAXPROCS(0)
|
return multiplier * runtime.GOMAXPROCS(0)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue