diff options
Diffstat (limited to 'src/rocksdb/examples/transaction_example.cc')
-rw-r--r-- | src/rocksdb/examples/transaction_example.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/rocksdb/examples/transaction_example.cc b/src/rocksdb/examples/transaction_example.cc new file mode 100644 index 000000000..41b233544 --- /dev/null +++ b/src/rocksdb/examples/transaction_example.cc @@ -0,0 +1,186 @@ +// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). + +#ifndef ROCKSDB_LITE + +#include "rocksdb/db.h" +#include "rocksdb/options.h" +#include "rocksdb/slice.h" +#include "rocksdb/utilities/transaction.h" +#include "rocksdb/utilities/transaction_db.h" + +using namespace ROCKSDB_NAMESPACE; + +std::string kDBPath = "/tmp/rocksdb_transaction_example"; + +int main() { + // open DB + Options options; + TransactionDBOptions txn_db_options; + options.create_if_missing = true; + TransactionDB* txn_db; + + Status s = TransactionDB::Open(options, txn_db_options, kDBPath, &txn_db); + assert(s.ok()); + + WriteOptions write_options; + ReadOptions read_options; + TransactionOptions txn_options; + std::string value; + + //////////////////////////////////////////////////////// + // + // Simple Transaction Example ("Read Committed") + // + //////////////////////////////////////////////////////// + + // Start a transaction + Transaction* txn = txn_db->BeginTransaction(write_options); + assert(txn); + + // Read a key in this transaction + s = txn->Get(read_options, "abc", &value); + assert(s.IsNotFound()); + + // Write a key in this transaction + s = txn->Put("abc", "def"); + assert(s.ok()); + + // Read a key OUTSIDE this transaction. Does not affect txn. + s = txn_db->Get(read_options, "abc", &value); + assert(s.IsNotFound()); + + // Write a key OUTSIDE of this transaction. + // Does not affect txn since this is an unrelated key. + s = txn_db->Put(write_options, "xyz", "zzz"); + assert(s.ok()); + + // Write a key OUTSIDE of this transaction. + // Fail because the key conflicts with the key written in txn. + s = txn_db->Put(write_options, "abc", "def"); + assert(s.subcode() == Status::kLockTimeout); + + // Value for key "xyz" has been committed, can be read in txn. + s = txn->Get(read_options, "xyz", &value); + assert(s.ok()); + assert(value == "zzz"); + + // Commit transaction + s = txn->Commit(); + assert(s.ok()); + delete txn; + + // Value is committed, can be read now. + s = txn_db->Get(read_options, "abc", &value); + assert(s.ok()); + assert(value == "def"); + + //////////////////////////////////////////////////////// + // + // "Repeatable Read" (Snapshot Isolation) Example + // -- Using a single Snapshot + // + //////////////////////////////////////////////////////// + + // Set a snapshot at start of transaction by setting set_snapshot=true + txn_options.set_snapshot = true; + txn = txn_db->BeginTransaction(write_options, txn_options); + + const Snapshot* snapshot = txn->GetSnapshot(); + + // Write a key OUTSIDE of transaction + s = txn_db->Put(write_options, "abc", "xyz"); + assert(s.ok()); + + // Read the latest committed value. + s = txn->Get(read_options, "abc", &value); + assert(s.ok()); + assert(value == "xyz"); + + // Read the snapshotted value. + read_options.snapshot = snapshot; + s = txn->Get(read_options, "abc", &value); + assert(s.ok()); + assert(value == "def"); + + // Attempt to read a key using the snapshot. This will fail since + // the previous write outside this txn conflicts with this read. + s = txn->GetForUpdate(read_options, "abc", &value); + assert(s.IsBusy()); + + txn->Rollback(); + + // Snapshot will be released upon deleting the transaction. + delete txn; + // Clear snapshot from read options since it is no longer valid + read_options.snapshot = nullptr; + snapshot = nullptr; + + //////////////////////////////////////////////////////// + // + // "Read Committed" (Monotonic Atomic Views) Example + // --Using multiple Snapshots + // + //////////////////////////////////////////////////////// + + // In this example, we set the snapshot multiple times. This is probably + // only necessary if you have very strict isolation requirements to + // implement. + + // Set a snapshot at start of transaction + txn_options.set_snapshot = true; + txn = txn_db->BeginTransaction(write_options, txn_options); + + // Do some reads and writes to key "x" + read_options.snapshot = txn_db->GetSnapshot(); + s = txn->Get(read_options, "x", &value); + assert(s.IsNotFound()); + s = txn->Put("x", "x"); + assert(s.ok()); + + // Do a write outside of the transaction to key "y" + s = txn_db->Put(write_options, "y", "y1"); + assert(s.ok()); + + // Set a new snapshot in the transaction + txn->SetSnapshot(); + txn->SetSavePoint(); + read_options.snapshot = txn_db->GetSnapshot(); + + // Do some reads and writes to key "y" + // Since the snapshot was advanced, the write done outside of the + // transaction does not conflict. + s = txn->GetForUpdate(read_options, "y", &value); + assert(s.ok()); + assert(value == "y1"); + s = txn->Put("y", "y2"); + assert(s.ok()); + + // Decide we want to revert the last write from this transaction. + txn->RollbackToSavePoint(); + + // Commit. + s = txn->Commit(); + assert(s.ok()); + delete txn; + // Clear snapshot from read options since it is no longer valid + read_options.snapshot = nullptr; + + // db state is at the save point. + s = txn_db->Get(read_options, "x", &value); + assert(s.ok()); + assert(value == "x"); + + s = txn_db->Get(read_options, "y", &value); + assert(s.ok()); + assert(value == "y1"); + + // Cleanup + delete txn_db; + DestroyDB(kDBPath, options); + return 0; +} + +#endif // ROCKSDB_LITE |