fix(sqlite): enable WAL + working busy timeout + _txlock=immediate to stop concurrent write lockouts (#7030)

* fix(sqlite): enable WAL + working busy timeout + _txlock=immediate to stop concurrent write lockouts
This commit is contained in:
Xayinn
2026-08-30 20:46:56 +08:00
committed by GitHub
parent b5b94bc685
commit 1751f43ee0
+21 -1
View File
@@ -41,4 +41,24 @@ func UsingLogDatabase(databaseType DatabaseType) bool {
return logDatabaseType == databaseType return logDatabaseType == databaseType
} }
var SQLitePath = "one-api.db?_busy_timeout=30000" // SQLitePath is the DSN for the default SQLite database. It uses WAL journal
// mode so readers are never blocked by the single writer, plus a 30s busy
// timeout for writers to queue.
//
// Two details are non-obvious and both are required for concurrent correctness:
//
// 1. The busy timeout must be passed as a `_pragma=busy_timeout(30000)` DSN
// parameter. The pure-Go driver (modernc.org/sqlite, used through
// github.com/glebarez/sqlite) silently ignores the plain `_busy_timeout=`
// form, so without this the effective timeout stays at SQLite's 5s default
// and concurrent writes surface as "database is locked" (see #6805).
//
// 2. `_txlock=immediate` (BEGIN IMMEDIATE) must be enabled. Without it, a
// transaction that first SELECTs (establishing a read snapshot) and then
// writes can hit SQLITE_BUSY_SNAPSHOT when another connection commits in
// between; the busy handler does not cover that case, so the write fails
// instantly no matter the timeout. BEGIN IMMEDIATE takes the write lock up
// front, so writers serialize through the busy timeout instead of dying on
// a stale snapshot. Autocommit SELECTs stay concurrent because WAL keeps
// readers unlocked.
var SQLitePath = "one-api.db?_pragma=busy_timeout(30000)&_pragma=journal_mode(WAL)&_txlock=immediate"