libstore: use sqlit3 IMMEDIATE transactions

The default transaction behavior (of Sqlite3) is DEFERRED.

DEFERRED means that the transaction does not actually start until the
database is first accessed. Internally, the BEGIN DEFERRED statement
merely sets a flag on the database connection that turns off the
automatic commit that would normally occur when the last statement
finishes. This causes the transaction that is automatically started to
persist until an explicit COMMIT or ROLLBACK or until a rollback is
provoked by an error or an ON CONFLICT ROLLBACK clause. If the first
statement after BEGIN DEFERRED is a SELECT, then a read transaction is
started. Subsequent write statements will upgrade the transaction to a
write transaction if possible, or return SQLITE_BUSY. If the first
statement after BEGIN DEFERRED is a write statement, then a write
transaction is started.

IMMEDIATE causes the database connection to start a new write
immediately, without waiting for a write statement. The BEGIN IMMEDIATE
might fail with SQLITE_BUSY if another write transaction is already
active on another database connection.

source: https://www.sqlite.org/lang_transaction.html#immediate

Because Nix only uses transactions for write operations, changing the
default will allow pushing the SQLITE_BUSY errors early instead of
mid-transaction.
This commit is contained in:
zimbatm 2024-10-19 10:35:02 +02:00
parent 694c378d14
commit 6357a7bf55

View File

@ -222,7 +222,7 @@ bool SQLiteStmt::Use::isNull(int col)
SQLiteTxn::SQLiteTxn(sqlite3 * db)
{
this->db = db;
if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
if (sqlite3_exec(db, "begin immediate transaction;", 0, 0, 0) != SQLITE_OK)
SQLiteError::throw_(db, "starting transaction");
active = true;
}