update
This commit is contained in:
+23
-11
@@ -43,23 +43,35 @@ func Open(driver, dsn string) (*DB, error) {
|
||||
sqlDriverName = name
|
||||
}
|
||||
|
||||
if d == "sqlite" {
|
||||
// Set these as mattn/go-sqlite3 DSN params, not a post-open PRAGMA
|
||||
// Exec: with more than one pooled connection, each new physical
|
||||
// connection database/sql opens is a fresh SQLite connection that
|
||||
// does NOT inherit a PRAGMA set on a different one (journal_mode is
|
||||
// the one exception — it's persisted in the DB file itself).
|
||||
// _foreign_keys and _busy_timeout must be per-connection, so they
|
||||
// have to ride in the DSN to apply to every connection the pool
|
||||
// ever opens, not just the first.
|
||||
sep := "?"
|
||||
if strings.Contains(dsn, "?") {
|
||||
sep = "&"
|
||||
}
|
||||
dsn += sep + "_journal_mode=WAL&_foreign_keys=on&_busy_timeout=5000"
|
||||
}
|
||||
|
||||
sqlDB, err := sql.Open(sqlDriverName, dsn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opening database: %w", err)
|
||||
}
|
||||
|
||||
if d == "sqlite" {
|
||||
// SQLite doesn't handle concurrent writers well — serialize via single conn.
|
||||
sqlDB.SetMaxOpenConns(1)
|
||||
if _, err := sqlDB.Exec("PRAGMA journal_mode=WAL"); err != nil {
|
||||
return nil, fmt.Errorf("enabling WAL mode: %w", err)
|
||||
}
|
||||
if _, err := sqlDB.Exec("PRAGMA foreign_keys=ON"); err != nil {
|
||||
return nil, fmt.Errorf("enabling foreign keys: %w", err)
|
||||
}
|
||||
if _, err := sqlDB.Exec("PRAGMA busy_timeout=5000"); err != nil {
|
||||
return nil, fmt.Errorf("setting busy timeout: %w", err)
|
||||
}
|
||||
// WAL mode already lets SQLite itself handle concurrent readers +
|
||||
// one writer (with _busy_timeout above covering writer contention) —
|
||||
// a small pool, not a single shared connection, so concurrent
|
||||
// requests across SMTP/IMAP/webmail/admin/etc. aren't all serialized
|
||||
// through one connection for no reason.
|
||||
sqlDB.SetMaxOpenConns(4)
|
||||
sqlDB.SetMaxIdleConns(4)
|
||||
}
|
||||
|
||||
if err := sqlDB.Ping(); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user