OptimisticTransactionDB provides optimistic concurrency control without locking during transaction execution. Conflicts are detected at commit time, making it ideal for workloads with low contention.
Opening an OptimisticTransactionDB
Open
static Status Open(
const Options& options,
const std::string& dbname,
OptimisticTransactionDB** dbptr
);
static Status Open(
const DBOptions& db_options,
const std::string& dbname,
const std::vector<ColumnFamilyDescriptor>& column_families,
std::vector<ColumnFamilyHandle*>* handles,
OptimisticTransactionDB** dbptr
);
static Status Open(
const DBOptions& db_options,
const OptimisticTransactionDBOptions& occ_options,
const std::string& dbname,
const std::vector<ColumnFamilyDescriptor>& column_families,
std::vector<ColumnFamilyHandle*>* handles,
OptimisticTransactionDB** dbptr
);
Opens an OptimisticTransactionDB similar to DB::Open().
occ_options
const OptimisticTransactionDBOptions&
Options specific to optimistic concurrency control.
Path to the database directory.
dbptr
OptimisticTransactionDB**
Output parameter for the opened database instance.
Returns OK on success, or an error status if the database cannot be opened.
Transaction Management
BeginTransaction
virtual Transaction* BeginTransaction(
const WriteOptions& write_options,
const OptimisticTransactionOptions& txn_options =
OptimisticTransactionOptions(),
Transaction* old_txn = nullptr
);
Starts a new optimistic transaction.
Write options for the transaction.
txn_options
const OptimisticTransactionOptions&
Transaction-specific options.
Optional transaction handle to reuse.
Returns a pointer to the new transaction. Caller is responsible for deletion.
Options and Configuration
OptimisticTransactionOptions
struct OptimisticTransactionOptions {
bool set_snapshot = false;
const Comparator* cmp = BytewiseComparator();
};
Whether to automatically set a snapshot at transaction start.
Comparator for the WriteBatchWithIndex. Should match the DB comparator.
OptimisticTransactionDBOptions
struct OptimisticTransactionDBOptions {
OccValidationPolicy validate_policy = OccValidationPolicy::kValidateParallel;
uint32_t occ_lock_buckets = (1 << 20);
std::shared_ptr<OccLockBuckets> shared_lock_buckets;
};
Validation strategy: kValidateSerial (in write-group) or kValidateParallel (before write-group).
Number of striped mutex locks for parallel validation. Larger values reduce contention but use more memory.
shared_lock_buckets
std::shared_ptr<OccLockBuckets>
Shared pool of mutex locks that can be shared among multiple databases.
Validation Policies
kValidateSerial
Validates serially at commit stage after entering the write-group. Single-threaded validation may suffer from mutex contention under high load.
kValidateParallel
Validates in parallel before entering the write-group. Each transaction acquires locks for its write-set in a well-defined order, reducing mutex contention.
Example
#include "rocksdb/utilities/optimistic_transaction_db.h"
using namespace ROCKSDB_NAMESPACE;
// Open OptimisticTransactionDB
Options options;
options.create_if_missing = true;
OptimisticTransactionDB* txn_db;
Status s = OptimisticTransactionDB::Open(options, "/tmp/testdb", &txn_db);
assert(s.ok());
// Start a transaction
WriteOptions write_options;
OptimisticTransactionOptions txn_options;
Transaction* txn = txn_db->BeginTransaction(write_options, txn_options);
// Write within transaction
s = txn->Put("key1", "value1");
assert(s.ok());
// Commit - will fail if there were conflicting writes
s = txn->Commit();
if (s.ok()) {
// Success
} else if (s.IsBusy()) {
// Conflict detected, retry transaction
}
delete txn;
delete txn_db;
Key Differences from TransactionDB
No Locking During Execution
OptimisticTransactionDB does not acquire locks during transaction execution. This provides better performance for read-heavy workloads and scenarios with low contention.
Conflict Detection at Commit
Conflicts are detected when Commit() is called. If another transaction modified the same keys, Commit() returns Status::Busy() and the transaction must be retried.
Better Concurrency
Without locking, optimistic transactions can achieve higher concurrency, especially for read-heavy workloads.
Lower Overhead
No lock management overhead makes optimistic transactions lighter weight than pessimistic transactions.
Limitations
Range Deletions Not Supported
Range deletions (including those in WriteBatch) are incompatible with OptimisticTransactionDB and will return a non-OK Status.
Higher Abort Rate Under Contention
With high write contention, the transaction abort rate can be high, requiring more retries.
See Also