Skip to main content
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().
options
const Options&
Database options.
occ_options
const OptimisticTransactionDBOptions&
Options specific to optimistic concurrency control.
dbname
const std::string&
Path to the database directory.
dbptr
OptimisticTransactionDB**
Output parameter for the opened database instance.
Status
Status
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
const WriteOptions&
Write options for the transaction.
txn_options
const OptimisticTransactionOptions&
Transaction-specific options.
old_txn
Transaction*
Optional transaction handle to reuse.
Transaction*
Transaction*
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();
};
set_snapshot
bool
Whether to automatically set a snapshot at transaction start.
cmp
const Comparator*
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;
};
validate_policy
OccValidationPolicy
Validation strategy: kValidateSerial (in write-group) or kValidateParallel (before write-group).
occ_lock_buckets
uint32_t
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

Build docs developers (and LLMs) love