Merge "libstore: use BEGIN IMMEDIATE SQLite transactions" into main
This commit is contained in:
@@ -1116,7 +1116,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
|
||||
return retrySQLite([&]() {
|
||||
auto state(_dbState.lockSync(always_progresses));
|
||||
|
||||
SQLiteTxn txn = state->db.beginTransaction();
|
||||
SQLiteTxn txn = state->db.beginTransaction(SQLiteTxnType::Immediate);
|
||||
StorePathSet paths;
|
||||
|
||||
for (auto & [_, i] : infos) {
|
||||
@@ -1508,7 +1508,7 @@ void LocalStore::invalidatePathChecked(const StorePath & path)
|
||||
retrySQLite([&]() {
|
||||
auto state(_dbState.lockSync(always_progresses));
|
||||
|
||||
SQLiteTxn txn = state->db.beginTransaction();
|
||||
SQLiteTxn txn = state->db.beginTransaction(SQLiteTxnType::Immediate);
|
||||
|
||||
if (isValidPath_(*state, path)) {
|
||||
StorePathSet referrers; queryReferrers(*state, path, referrers);
|
||||
@@ -1772,7 +1772,7 @@ void LocalStore::addSignatures(const StorePath & storePath, const StringSet & si
|
||||
retrySQLite([&]() {
|
||||
auto state(_dbState.lockSync(always_progresses));
|
||||
|
||||
SQLiteTxn txn = state->db.beginTransaction();
|
||||
SQLiteTxn txn = state->db.beginTransaction(SQLiteTxnType::Immediate);
|
||||
|
||||
auto info = std::const_pointer_cast<ValidPathInfo>(queryPathInfoInternal(*state, storePath));
|
||||
|
||||
|
||||
+15
-4
@@ -117,9 +117,9 @@ SQLiteStmt SQLite::create(const std::string & stmt)
|
||||
return SQLiteStmt(db.get(), stmt);
|
||||
}
|
||||
|
||||
SQLiteTxn SQLite::beginTransaction()
|
||||
SQLiteTxn SQLite::beginTransaction(SQLiteTxnType type)
|
||||
{
|
||||
return SQLiteTxn(db.get());
|
||||
return SQLiteTxn(db.get(), type);
|
||||
}
|
||||
|
||||
void SQLite::setPersistWAL(bool persist)
|
||||
@@ -253,9 +253,20 @@ bool SQLiteStmt::Use::isNull(int col)
|
||||
return sqlite3_column_type(stmt.stmt.get(), col) == SQLITE_NULL;
|
||||
}
|
||||
|
||||
SQLiteTxn::SQLiteTxn(sqlite3 * db)
|
||||
SQLiteTxn::SQLiteTxn(sqlite3 * db, SQLiteTxnType type)
|
||||
{
|
||||
if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
|
||||
const char * sql = "begin;";
|
||||
switch (type) {
|
||||
case SQLiteTxnType::Deferred:
|
||||
break;
|
||||
case SQLiteTxnType::Immediate:
|
||||
sql = "begin immediate;";
|
||||
break;
|
||||
case SQLiteTxnType::Exclusive:
|
||||
sql = "begin exclusive;";
|
||||
break;
|
||||
}
|
||||
if (sqlite3_exec(db, sql, 0, 0, 0) != SQLITE_OK)
|
||||
SQLiteError::throw_(db, "starting transaction");
|
||||
this->db.reset(db);
|
||||
}
|
||||
|
||||
+26
-2
@@ -37,6 +37,30 @@ enum class SQLiteOpenMode {
|
||||
Immutable,
|
||||
};
|
||||
|
||||
enum class SQLiteTxnType {
|
||||
/**
|
||||
* A deferred transaction does not actually begin until the database is first accessed.
|
||||
* If the first statement in the transaction 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 another write transaction started on another database connection.
|
||||
* If the first statement in the transaction is a write statement then a write transaction
|
||||
* is started.
|
||||
*/
|
||||
Deferred,
|
||||
/**
|
||||
* An immediate transaction causes the database to start a write transaction immediately,
|
||||
* without waiting for a write statement. The transaction might fail wth SQLITE_BUSY if another
|
||||
* write transaction is already active on another database connection.
|
||||
*/
|
||||
Immediate,
|
||||
/**
|
||||
* An exclusive transaction causes the database to start a write transaction immediately.
|
||||
* In WAL mode this is the same as Immediate, but in other journaling modes this prevents
|
||||
* other database connections from reading the database while a transction is underway.
|
||||
*/
|
||||
Exclusive,
|
||||
};
|
||||
|
||||
struct SQLiteError;
|
||||
class SQLiteStmt;
|
||||
class SQLiteTxn;
|
||||
@@ -66,7 +90,7 @@ public:
|
||||
|
||||
SQLiteStmt create(const std::string & stmt);
|
||||
|
||||
SQLiteTxn beginTransaction();
|
||||
SQLiteTxn beginTransaction(SQLiteTxnType type = SQLiteTxnType::Deferred);
|
||||
|
||||
void setPersistWAL(bool persist);
|
||||
|
||||
@@ -154,7 +178,7 @@ class SQLiteTxn
|
||||
};
|
||||
std::unique_ptr<sqlite3, Rollback> db;
|
||||
|
||||
explicit SQLiteTxn(sqlite3 * db);
|
||||
explicit SQLiteTxn(sqlite3 * db, SQLiteTxnType type);
|
||||
|
||||
public:
|
||||
void commit();
|
||||
|
||||
Reference in New Issue
Block a user