mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-11 23:30:05 +02:00
sqlite: Ensure that only one SQLiteBatch is writing to db at a time
A SQLiteBatch need to wait for any other batch to finish writing before it can begin writing, otherwise db txn state may be incorrectly modified. To enforce this, each SQLiteDatabase has a semaphore which acts as a lock and is acquired by a batch when it begins a write, erase, or a transaction, and is released by it when it is done. To avoid deadlocking on itself for writing during a transaction, SQLiteBatch also keeps track of whether it has begun a transaction.
This commit is contained in:
@@ -58,6 +58,18 @@ private:
|
||||
sqlite3_stmt* m_delete_stmt{nullptr};
|
||||
sqlite3_stmt* m_delete_prefix_stmt{nullptr};
|
||||
|
||||
/** Whether this batch has started a database transaction and whether it owns SQLiteDatabase::m_write_semaphore.
|
||||
* If the batch starts a db tx, it acquires the semaphore and sets this to true, keeping the semaphore
|
||||
* until the transaction ends to prevent other batch objects from writing to the database.
|
||||
*
|
||||
* If this batch did not start a transaction, the semaphore is acquired transiently when writing and m_txn
|
||||
* is not set.
|
||||
*
|
||||
* m_txn is different from HasActiveTxn() as it is only true when this batch has started the transaction,
|
||||
* not just when any batch has started a transaction.
|
||||
*/
|
||||
bool m_txn{false};
|
||||
|
||||
void SetupSQLStatements();
|
||||
bool ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob);
|
||||
|
||||
@@ -115,6 +127,10 @@ public:
|
||||
|
||||
~SQLiteDatabase();
|
||||
|
||||
// Batches must acquire this semaphore on writing, and release when done writing.
|
||||
// This ensures that only one batch is modifying the database at a time.
|
||||
CSemaphore m_write_semaphore;
|
||||
|
||||
bool Verify(bilingual_str& error);
|
||||
|
||||
/** Open the database if it is not already opened */
|
||||
|
||||
Reference in New Issue
Block a user