optimistic_transaction_example.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #include "rocksdb/db.h"
  6. #include "rocksdb/options.h"
  7. #include "rocksdb/slice.h"
  8. #include "rocksdb/utilities/optimistic_transaction_db.h"
  9. #include "rocksdb/utilities/transaction.h"
  10. using ROCKSDB_NAMESPACE::DB;
  11. using ROCKSDB_NAMESPACE::OptimisticTransactionDB;
  12. using ROCKSDB_NAMESPACE::OptimisticTransactionOptions;
  13. using ROCKSDB_NAMESPACE::Options;
  14. using ROCKSDB_NAMESPACE::ReadOptions;
  15. using ROCKSDB_NAMESPACE::Snapshot;
  16. using ROCKSDB_NAMESPACE::Status;
  17. using ROCKSDB_NAMESPACE::Transaction;
  18. using ROCKSDB_NAMESPACE::WriteOptions;
  19. #if defined(OS_WIN)
  20. std::string kDBPath = "C:\\Windows\\TEMP\\rocksdb_transaction_example";
  21. #else
  22. std::string kDBPath = "/tmp/rocksdb_transaction_example";
  23. #endif
  24. int main() {
  25. // open DB
  26. Options options;
  27. options.create_if_missing = true;
  28. DB* db;
  29. OptimisticTransactionDB* txn_db;
  30. Status s = OptimisticTransactionDB::Open(options, kDBPath, &txn_db);
  31. assert(s.ok());
  32. db = txn_db->GetBaseDB();
  33. WriteOptions write_options;
  34. ReadOptions read_options;
  35. OptimisticTransactionOptions txn_options;
  36. std::string value;
  37. ////////////////////////////////////////////////////////
  38. //
  39. // Simple OptimisticTransaction Example ("Read Committed")
  40. //
  41. ////////////////////////////////////////////////////////
  42. // Start a transaction
  43. Transaction* txn = txn_db->BeginTransaction(write_options);
  44. assert(txn);
  45. // Read a key in this transaction
  46. s = txn->Get(read_options, "abc", &value);
  47. assert(s.IsNotFound());
  48. // Write a key in this transaction
  49. s = txn->Put("abc", "xyz");
  50. assert(s.ok());
  51. // Read a key OUTSIDE this transaction. Does not affect txn.
  52. s = db->Get(read_options, "abc", &value);
  53. assert(s.IsNotFound());
  54. // Write a key OUTSIDE of this transaction.
  55. // Does not affect txn since this is an unrelated key. If we wrote key 'abc'
  56. // here, the transaction would fail to commit.
  57. s = db->Put(write_options, "xyz", "zzz");
  58. assert(s.ok());
  59. s = db->Put(write_options, "abc", "def");
  60. assert(s.ok());
  61. // Commit transaction
  62. s = txn->Commit();
  63. assert(s.IsBusy());
  64. delete txn;
  65. s = db->Get(read_options, "xyz", &value);
  66. assert(s.ok());
  67. assert(value == "zzz");
  68. s = db->Get(read_options, "abc", &value);
  69. assert(s.ok());
  70. assert(value == "def");
  71. ////////////////////////////////////////////////////////
  72. //
  73. // "Repeatable Read" (Snapshot Isolation) Example
  74. // -- Using a single Snapshot
  75. //
  76. ////////////////////////////////////////////////////////
  77. // Set a snapshot at start of transaction by setting set_snapshot=true
  78. txn_options.set_snapshot = true;
  79. txn = txn_db->BeginTransaction(write_options, txn_options);
  80. const Snapshot* snapshot = txn->GetSnapshot();
  81. // Write a key OUTSIDE of transaction
  82. s = db->Put(write_options, "abc", "xyz");
  83. assert(s.ok());
  84. // Read a key using the snapshot
  85. read_options.snapshot = snapshot;
  86. s = txn->GetForUpdate(read_options, "abc", &value);
  87. assert(s.ok());
  88. assert(value == "def");
  89. // Attempt to commit transaction
  90. s = txn->Commit();
  91. // Transaction could not commit since the write outside of the txn conflicted
  92. // with the read!
  93. assert(s.IsBusy());
  94. delete txn;
  95. // Clear snapshot from read options since it is no longer valid
  96. read_options.snapshot = nullptr;
  97. snapshot = nullptr;
  98. s = db->Get(read_options, "abc", &value);
  99. assert(s.ok());
  100. assert(value == "xyz");
  101. ////////////////////////////////////////////////////////
  102. //
  103. // "Read Committed" (Monotonic Atomic Views) Example
  104. // --Using multiple Snapshots
  105. //
  106. ////////////////////////////////////////////////////////
  107. // In this example, we set the snapshot multiple times. This is probably
  108. // only necessary if you have very strict isolation requirements to
  109. // implement.
  110. // Set a snapshot at start of transaction
  111. txn_options.set_snapshot = true;
  112. txn = txn_db->BeginTransaction(write_options, txn_options);
  113. // Do some reads and writes to key "x"
  114. read_options.snapshot = db->GetSnapshot();
  115. s = txn->Get(read_options, "x", &value);
  116. assert(s.IsNotFound());
  117. s = txn->Put("x", "x");
  118. assert(s.ok());
  119. // The transaction hasn't committed, so the write is not visible
  120. // outside of txn.
  121. s = db->Get(read_options, "x", &value);
  122. assert(s.IsNotFound());
  123. // Do a write outside of the transaction to key "y"
  124. s = db->Put(write_options, "y", "z");
  125. assert(s.ok());
  126. // Set a new snapshot in the transaction
  127. txn->SetSnapshot();
  128. read_options.snapshot = db->GetSnapshot();
  129. // Do some reads and writes to key "y"
  130. s = txn->GetForUpdate(read_options, "y", &value);
  131. assert(s.ok());
  132. assert(value == "z");
  133. txn->Put("y", "y");
  134. // Commit. Since the snapshot was advanced, the write done outside of the
  135. // transaction does not prevent this transaction from Committing.
  136. s = txn->Commit();
  137. assert(s.ok());
  138. delete txn;
  139. // Clear snapshot from read options since it is no longer valid
  140. read_options.snapshot = nullptr;
  141. // txn is committed, read the latest values.
  142. s = db->Get(read_options, "x", &value);
  143. assert(s.ok());
  144. assert(value == "x");
  145. s = db->Get(read_options, "y", &value);
  146. assert(s.ok());
  147. assert(value == "y");
  148. // Cleanup
  149. delete txn_db;
  150. DestroyDB(kDBPath, options);
  151. return 0;
  152. }